0dcbcf3ac8ce47314a82330762a6bf4b2901ee76
[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.Length();
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.Length();
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.Length();
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.Length();
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.Length();
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   TopTools_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.Length();
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.Length();
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         Standard_Boolean aCurrentFind = Standard_False;
2369         if (itry == 1) {
2370           fl1[0] = C1->FirstParameter(); fl1[1] = C1->LastParameter();
2371           fl2[0] = C2->FirstParameter(); fl2[1] = C2->LastParameter();
2372         }
2373         Geom2dAdaptor_Curve   AC1(C1,fl1[0],fl1[1]);
2374         Geom2dAdaptor_Curve   AC2(C2,fl2[0],fl2[1]);
2375
2376         if (itry == 0) {
2377           gp_Pnt2d P1[2],P2[2];
2378           P1[0] = C1->Value(fl1[0]); P1[1] = C1->Value(fl1[1]);
2379           P2[0] = C2->Value(fl2[0]); P2[1] = C2->Value(fl2[1]);
2380
2381           Standard_Integer i1 ;
2382           for ( i1 = 0; i1 < 2; i1++) {
2383             for (Standard_Integer i2 = 0; i2 < 2; i2++) {
2384               if (Abs(fl1[i1]) < Precision::Infinite() &&
2385                   Abs(fl2[i2]) < Precision::Infinite()   ) {
2386                 if (P1[i1].IsEqual(P2[i2],TolConf)) {
2387                   YaSol = Standard_True;
2388                   aCurrentFind = Standard_True;
2389                   U1  = fl1[i1]; U2 = fl2[i2];
2390                   P2d = C1->Value(U1);
2391                 }
2392               }
2393             }
2394           }
2395           if (!YaSol)
2396             for (i1 = 0; i1 < 2; i1++)
2397               {
2398                 Extrema_ExtPC2d extr( P1[i1], AC2 );
2399                 if (extr.IsDone() && extr.NbExt() > 0)
2400                   {
2401                     Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2402                     Standard_Integer IndexMin = 1;
2403                     for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2404                       {
2405                         Dist2 = extr.SquareDistance(ind);
2406                         if (Dist2 < Dist2Min)
2407                           {
2408                             Dist2Min = Dist2;
2409                             IndexMin = ind;
2410                           }
2411                       }
2412             if (Dist2Min <= Precision::SquareConfusion())
2413                       {
2414                         YaSol = Standard_True;
2415                         aCurrentFind = Standard_True;
2416                         P2d = P1[i1];
2417                         U1 = fl1[i1];
2418                         U2 = (extr.Point(IndexMin)).Parameter();
2419                         break;
2420                       }
2421                   }
2422               }
2423           if (!YaSol)
2424             for (Standard_Integer i2 = 0; i2 < 2; i2++)
2425               {
2426                 Extrema_ExtPC2d extr( P2[i2], AC1 );
2427                 if (extr.IsDone() && extr.NbExt() > 0)
2428                   {
2429                     Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2430                     Standard_Integer IndexMin = 1;
2431                     for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2432                       {
2433                         Dist2 = extr.SquareDistance(ind);
2434                         if (Dist2 < Dist2Min)
2435                           {
2436                             Dist2Min = Dist2;
2437                             IndexMin = ind;
2438                           }
2439                       }
2440             if (Dist2Min <= Precision::SquareConfusion())
2441                       {
2442                         YaSol = Standard_True;
2443                         aCurrentFind = Standard_True;
2444                         P2d = P2[i2];
2445                         U2 = fl2[i2];
2446                         U1 = (extr.Point(IndexMin)).Parameter();
2447                         break;
2448                       }
2449                   }
2450               }
2451         }
2452         
2453         if (!YaSol) {
2454           Geom2dInt_GInter Inter (AC1,AC2,TolConf,TolConf);
2455           
2456           if (!Inter.IsEmpty() && Inter.NbPoints() > 0) {
2457                   YaSol = Standard_True;
2458                   aCurrentFind = Standard_True;
2459             U1  = Inter.Point(1).ParamOnFirst();
2460             U2  = Inter.Point(1).ParamOnSecond();
2461             P2d = Inter.Point(1).Value();
2462           }
2463           else if (!Inter.IsEmpty() && Inter.NbSegments() > 0) {
2464                           YaSol = Standard_True;
2465                   aCurrentFind = Standard_True;
2466             IntRes2d_IntersectionSegment Seg = Inter.Segment(1);
2467             IntRes2d_IntersectionPoint IntP1 = Seg.FirstPoint();
2468             IntRes2d_IntersectionPoint IntP2 = Seg.LastPoint();
2469             Standard_Real U1on1 = IntP1.ParamOnFirst();
2470             Standard_Real U1on2 = IntP2.ParamOnFirst();
2471             Standard_Real U2on1 = IntP1.ParamOnSecond();
2472             Standard_Real U2on2 = IntP2.ParamOnSecond();
2473 #ifdef OCCT_DEBUG
2474             cout << " BRepOffset_Tool::Inter2d SEGMENT d intersection" << endl;
2475             cout << "     ===> Parametres sur Curve1 : ";
2476             cout << U1on1 << " " << U1on2 << endl;
2477             cout << "     ===> Parametres sur Curve2 : ";
2478             cout << U2on1 << " " << U2on2 << endl;
2479 #endif
2480             U1 = (U1on1 + U1on2)/2.;
2481             U2 = (U2on1 + U2on2)/2.;
2482             gp_Pnt2d P2d1 = C1->Value(U1);
2483             gp_Pnt2d P2d2 = C2->Value(U2);
2484             P2d.SetX( (P2d1.X() + P2d2.X()) / 2.);
2485             P2d.SetY( (P2d1.Y() + P2d2.Y()) / 2.);
2486           }
2487         }
2488         if (aCurrentFind) {
2489           gp_Pnt        P   = S->Value(P2d.X(),P2d.Y());
2490           TopoDS_Vertex V = BRepLib_MakeVertex(P);
2491           V.Orientation(TopAbs_INTERNAL);
2492           TopoDS_Shape aLocalEdgeOrientedE1 = E1.Oriented(TopAbs_FORWARD);
2493           B.UpdateVertex(V,U1,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2494           aLocalEdgeOrientedE1 = E2.Oriented(TopAbs_FORWARD);
2495           B.UpdateVertex(V,U2,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2496 //        B.UpdateVertex(V,U1,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)),TolConf);
2497 //        B.UpdateVertex(V,U2,TopoDS::Edge(E2.Oriented(TopAbs_FORWARD)),TolConf);
2498           LV.Append(V);
2499         }
2500       }
2501     }
2502     itry++;
2503   }
2504
2505   if (LV.Extent() > 1) {
2506     //------------------------------------------------
2507     // garde seulement les vertex les plus proches du 
2508     //debut et de la fin. 
2509     //------------------------------------------------
2510     TopTools_ListIteratorOfListOfShape it(LV);
2511     TopoDS_Vertex         VF,VL;
2512     Standard_Real         UMin =  Precision::Infinite();
2513     Standard_Real         UMax = -Precision::Infinite();
2514     Standard_Real         U;
2515
2516     for ( ; it.More(); it.Next()) {
2517       TopoDS_Vertex CV = TopoDS::Vertex(it.Value());
2518       TopoDS_Shape aLocalEdge = E1.Oriented(TopAbs_FORWARD);
2519       U = BRep_Tool::Parameter(CV,TopoDS::Edge(aLocalEdge));
2520 //      U = BRep_Tool::Parameter(CV,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)));
2521       if ( U < UMin) {
2522         VF = CV; UMin = U;
2523       }
2524       if ( U > UMax) {
2525         VL = CV; UMax = U;
2526       }
2527     }
2528     LV.Clear();LV.Append(VF); LV.Append(VL);
2529   }
2530
2531 #ifdef OCCT_DEBUG
2532   if (!YaSol) {
2533     cout <<"Inter2d : Pas de solution"<<endl;
2534 #ifdef DRAW
2535     DBRep::Set("E1",E1); 
2536     DBRep::Set("E2",E2);
2537     DBRep::Set("F",F);
2538 #endif
2539   }
2540 #endif    
2541 }
2542
2543 //=======================================================================
2544 //function : SelectEdge
2545 //purpose  : 
2546 //=======================================================================
2547
2548 static void SelectEdge (const TopoDS_Face& /*F*/,
2549                         const TopoDS_Face& /*EF*/,
2550                         const TopoDS_Edge& E,
2551                         TopTools_ListOfShape& LInt)
2552 {
2553  //------------------------------------------------------------
2554   // detrompeur sur les intersections sur les faces periodiques
2555   //------------------------------------------------------------
2556    TopTools_ListIteratorOfListOfShape it(LInt);
2557   Standard_Real dU = 1.0e100;
2558   TopoDS_Edge   GE;
2559
2560   Standard_Real Fst, Lst, tmp;
2561   BRep_Tool::Range(E, Fst, Lst);
2562   BRepAdaptor_Curve  Ad1(E);
2563  
2564   gp_Pnt PFirst = Ad1.Value( Fst );  
2565   gp_Pnt PLast  = Ad1.Value( Lst );  
2566
2567   //----------------------------------------------------------------------
2568   // Selection de l edge qui couvre le plus le domaine de l edge initiale.
2569   //---------------------------------------------------------------------- 
2570   for (; it.More(); it.Next()) {
2571     const TopoDS_Edge& EI = TopoDS::Edge(it.Value());
2572
2573     BRep_Tool::Range(EI, Fst, Lst);
2574     BRepAdaptor_Curve  Ad2(EI);
2575     gp_Pnt P1 = Ad2.Value(Fst);
2576     gp_Pnt P2 = Ad2.Value(Lst);
2577        
2578     tmp = P1.Distance(PFirst) + P2.Distance(PLast);
2579     if( tmp <= dU ) {
2580       dU = tmp;
2581       GE = EI;
2582     } 
2583
2584   }
2585   LInt.Clear(); 
2586   LInt.Append(GE);
2587 }
2588
2589
2590 //=======================================================================
2591 //function : Init
2592 //purpose  : 
2593 //=======================================================================
2594
2595 static void MakeFace(const Handle(Geom_Surface)& S,
2596                      const Standard_Real Um,
2597                      const Standard_Real UM,
2598                      const Standard_Real Vm,
2599                      const Standard_Real VM,
2600                      const Standard_Boolean isVminDegen,
2601                      const Standard_Boolean isVmaxDegen,
2602                      TopoDS_Face&        F)
2603 {
2604   Standard_Real UMin = Um;
2605   Standard_Real UMax = UM;
2606   Standard_Real VMin = Vm;
2607   Standard_Real VMax = VM;
2608   Standard_Real epsilon = Precision::Confusion();
2609
2610   Standard_Real umin,umax,vmin,vmax;
2611   S->Bounds(umin,umax,vmin,vmax);
2612
2613
2614   // compute infinite flags
2615   Standard_Boolean umininf = Precision::IsNegativeInfinite(UMin);
2616   Standard_Boolean umaxinf = Precision::IsPositiveInfinite(UMax);
2617   Standard_Boolean vmininf = Precision::IsNegativeInfinite(VMin);
2618   Standard_Boolean vmaxinf = Precision::IsPositiveInfinite(VMax);
2619   
2620   // closed flag
2621   Standard_Boolean IsSuclosed = S->IsUClosed(), IsSvclosed = S->IsVClosed();
2622   if (S->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2623     {
2624       Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (S)->BasisSurface();
2625       IsSuclosed = BasisSurf->IsUClosed();
2626       IsSvclosed = BasisSurf->IsVClosed();
2627     }
2628
2629   Standard_Boolean uclosed = 
2630     IsSuclosed && 
2631       Abs(UMin - umin) < epsilon && 
2632         Abs(UMax - umax) < epsilon;
2633   
2634   Standard_Boolean vclosed = 
2635     IsSvclosed && 
2636       Abs(VMin - vmin) < epsilon && 
2637         Abs(VMax - vmax) < epsilon;
2638   
2639   // degenerated flags (for cones)
2640   Standard_Boolean vmindegen = isVminDegen, vmaxdegen = isVmaxDegen;
2641   Handle(Geom_Surface) theSurf = S;
2642   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
2643     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2644   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
2645     {
2646       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
2647       gp_Cone theCone = ConicalS->Cone();
2648       gp_Pnt theApex = theCone.Apex();
2649       Standard_Real Uapex, Vapex;
2650       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
2651       if (Abs(VMin - Vapex) <= Precision::Confusion())
2652         vmindegen = Standard_True;
2653       if (Abs(VMax - Vapex) <= Precision::Confusion())
2654         vmaxdegen = Standard_True;
2655     }
2656   
2657   // compute vertices
2658   BRep_Builder B;
2659   Standard_Real tol = Precision::Confusion();
2660   
2661   TopoDS_Vertex V00,V10,V11,V01;
2662   
2663   if (!umininf) {
2664     if (!vmininf) B.MakeVertex(V00,S->Value(UMin,VMin),tol);
2665     if (!vmaxinf) B.MakeVertex(V01,S->Value(UMin,VMax),tol);
2666   }
2667   if (!umaxinf) {
2668     if (!vmininf) B.MakeVertex(V10,S->Value(UMax,VMin),tol);
2669     if (!vmaxinf) B.MakeVertex(V11,S->Value(UMax,VMax),tol);
2670   }
2671
2672   if (uclosed) {
2673     V10 = V00;
2674     V11 = V01;
2675   }
2676
2677   if (vclosed) {
2678     V01 = V00;
2679     V11 = V10;
2680   }
2681
2682   if (vmindegen)
2683     V10 = V00;
2684   if (vmaxdegen)
2685     V11 = V01;
2686
2687   // make the lines
2688   Handle(Geom2d_Line) Lumin,Lumax,Lvmin,Lvmax;
2689   if (!umininf)
2690     Lumin = new Geom2d_Line(gp_Pnt2d(UMin,0),gp_Dir2d(0,1));
2691   if (!umaxinf)
2692     Lumax = new Geom2d_Line(gp_Pnt2d(UMax,0),gp_Dir2d(0,1));
2693   if (!vmininf)
2694     Lvmin = new Geom2d_Line(gp_Pnt2d(0,VMin),gp_Dir2d(1,0));
2695   if (!vmaxinf)
2696     Lvmax = new Geom2d_Line(gp_Pnt2d(0,VMax),gp_Dir2d(1,0));
2697   
2698   Handle(Geom_Curve) Cumin,Cumax,Cvmin,Cvmax;
2699   Standard_Real TolApex = 1.e-5;
2700   //Standard_Boolean hasiso = ! S->IsKind(STANDARD_TYPE(Geom_OffsetSurface));
2701   Standard_Boolean hasiso = S->IsKind(STANDARD_TYPE(Geom_ElementarySurface));
2702   if (hasiso) {
2703     if (!umininf)
2704       Cumin = S->UIso(UMin);
2705     if (!umaxinf)
2706       Cumax = S->UIso(UMax);
2707     if (!vmininf)
2708       {
2709         Cvmin = S->VIso(VMin);
2710         if (BRepOffset_Tool::Gabarit( Cvmin ) <= TolApex)
2711           vmindegen = Standard_True;
2712       }
2713     if (!vmaxinf)
2714       {
2715         Cvmax = S->VIso(VMax);
2716         if (BRepOffset_Tool::Gabarit( Cvmax ) <= TolApex)
2717           vmaxdegen = Standard_True;
2718       }
2719   }
2720
2721   // make the face
2722   B.MakeFace(F,S,tol);
2723
2724   // make the edges
2725   TopoDS_Edge eumin,eumax,evmin,evmax;
2726
2727   if (!umininf) {
2728     if (hasiso)
2729       B.MakeEdge(eumin,Cumin,tol);
2730     else
2731       B.MakeEdge(eumin);
2732     if (uclosed) 
2733       B.UpdateEdge(eumin,Lumax,Lumin,F,tol);
2734     else
2735       B.UpdateEdge(eumin,Lumin,F,tol);
2736     if (!vmininf) {
2737       V00.Orientation(TopAbs_FORWARD);
2738       B.Add(eumin,V00);
2739     }
2740     if (!vmaxinf) {
2741       V01.Orientation(TopAbs_REVERSED);
2742       B.Add(eumin,V01);
2743     }
2744     B.Range(eumin,VMin,VMax);
2745   }
2746
2747   if (!umaxinf) {
2748     if (uclosed)
2749       eumax = eumin;
2750     else {
2751       if (hasiso)
2752         B.MakeEdge(eumax,Cumax,tol);
2753       else
2754         B.MakeEdge(eumax);
2755       B.UpdateEdge(eumax,Lumax,F,tol);
2756       if (!vmininf) {
2757         V10.Orientation(TopAbs_FORWARD);
2758         B.Add(eumax,V10);
2759       }
2760       if (!vmaxinf) {
2761         V11.Orientation(TopAbs_REVERSED);
2762         B.Add(eumax,V11);
2763       }
2764       B.Range(eumax,VMin,VMax);
2765     }
2766   }
2767
2768   if (!vmininf) {
2769     if (hasiso && !vmindegen)
2770       B.MakeEdge(evmin,Cvmin,tol);
2771     else
2772       B.MakeEdge(evmin);
2773     if (vclosed)
2774       B.UpdateEdge(evmin,Lvmin,Lvmax,F,tol);
2775     else
2776       B.UpdateEdge(evmin,Lvmin,F,tol);
2777     if (!umininf) {
2778       V00.Orientation(TopAbs_FORWARD);
2779       B.Add(evmin,V00);
2780     }
2781     if (!umaxinf) {
2782       V10.Orientation(TopAbs_REVERSED);
2783       B.Add(evmin,V10);
2784     }
2785     B.Range(evmin,UMin,UMax);
2786     if (vmindegen)
2787       B.Degenerated(evmin, Standard_True);
2788   }
2789
2790   if (!vmaxinf) {
2791     if (vclosed)
2792       evmax = evmin;
2793     else {
2794       if (hasiso && !vmaxdegen)
2795         B.MakeEdge(evmax,Cvmax,tol);
2796       else
2797         B.MakeEdge(evmax);
2798       B.UpdateEdge(evmax,Lvmax,F,tol);
2799       if (!umininf) {
2800         V01.Orientation(TopAbs_FORWARD);
2801         B.Add(evmax,V01);
2802       }
2803       if (!umaxinf) {
2804         V11.Orientation(TopAbs_REVERSED);
2805         B.Add(evmax,V11);
2806       }
2807       B.Range(evmax,UMin,UMax);
2808       if (vmaxdegen)
2809         B.Degenerated(evmax, Standard_True);
2810     }
2811   }
2812
2813   // make the wires and add them to the face
2814   eumin.Orientation(TopAbs_REVERSED);
2815   evmax.Orientation(TopAbs_REVERSED);
2816   
2817   TopoDS_Wire W;
2818
2819   if (!umininf && !umaxinf && vmininf && vmaxinf) {
2820     // two wires in u
2821     B.MakeWire(W);
2822     B.Add(W,eumin);
2823     B.Add(F,W);
2824     B.MakeWire(W);
2825     B.Add(W,eumax);
2826     B.Add(F,W);
2827     F.Closed(uclosed);
2828   }
2829     
2830   else if (umininf && umaxinf && !vmininf && !vmaxinf) {
2831     // two wires in v
2832     B.MakeWire(W);
2833     B.Add(W,evmin);
2834     B.Add(F,W);
2835     B.MakeWire(W);
2836     B.Add(W,evmax);
2837     B.Add(F,W);
2838     F.Closed(vclosed);
2839   }
2840     
2841   else if (!umininf || !umaxinf || !vmininf || !vmaxinf) {
2842     // one wire
2843     B.MakeWire(W);
2844     if (!umininf) B.Add(W,eumin);
2845     if (!vmininf) B.Add(W,evmin);
2846     if (!umaxinf) B.Add(W,eumax);
2847     if (!vmaxinf) B.Add(W,evmax);
2848     B.Add(F,W);
2849     W.Closed(!umininf && !umaxinf && !vmininf && !vmaxinf);
2850     F.Closed(uclosed && vclosed);
2851   }
2852 }
2853
2854 //=======================================================================
2855 //function : EnLargeGeometry
2856 //purpose  : 
2857 //=======================================================================
2858
2859 static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S,
2860                                         Standard_Real&        U1,
2861                                         Standard_Real&        U2,
2862                                         Standard_Real&        V1,
2863                                         Standard_Real&        V2,
2864                                         Standard_Boolean&     IsV1degen,
2865                                         Standard_Boolean&     IsV2degen,
2866                                         const Standard_Real   uf1,
2867                                         const Standard_Real   uf2,
2868                                         const Standard_Real   vf1,
2869                                         const Standard_Real   vf2,
2870                                         const Standard_Boolean GlobalEnlargeU,
2871                                         const Standard_Boolean GlobalEnlargeVfirst,
2872                                         const Standard_Boolean GlobalEnlargeVlast)
2873 {
2874   const Standard_Real coeff = 4.;
2875   const Standard_Real TolApex = 1.e-5;
2876
2877   Standard_Boolean SurfaceChange = Standard_False;
2878   if ( S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2879     Handle(Geom_Surface) BS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2880     EnlargeGeometry(BS,U1,U2,V1,V2,IsV1degen,IsV2degen,
2881                     uf1,uf2,vf1,vf2,GlobalEnlargeU,GlobalEnlargeVfirst,GlobalEnlargeVlast);
2882     if (!GlobalEnlargeVfirst)
2883       V1 = vf1;
2884     if (!GlobalEnlargeVlast)
2885       V2 = vf2;
2886     if (!GlobalEnlargeVfirst || !GlobalEnlargeVlast)
2887       //Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->SetTrim( U1, U2, V1, V2 );
2888       S = new Geom_RectangularTrimmedSurface( BS, U1, U2, V1, V2 );
2889     else
2890       S = BS;
2891     SurfaceChange = Standard_True;
2892   }
2893   else if (S->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)) {
2894     Handle(Geom_Surface) Surf = Handle(Geom_OffsetSurface)::DownCast (S)->BasisSurface();
2895     SurfaceChange = EnlargeGeometry(Surf,U1,U2,V1,V2,IsV1degen,IsV2degen,
2896                                     uf1,uf2,vf1,vf2,GlobalEnlargeU,GlobalEnlargeVfirst,GlobalEnlargeVlast);
2897     Handle(Geom_OffsetSurface)::DownCast(S)->SetBasisSurface(Surf);
2898   }
2899   else if (S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
2900            S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution))
2901     {
2902       Standard_Real du=0., dv=0.;
2903       Handle( Geom_Curve ) uiso, viso, uiso1, uiso2, viso1, viso2;
2904       Standard_Real u1, u2, v1, v2;
2905       Standard_Boolean enlargeU = GlobalEnlargeU, enlargeV = Standard_True;
2906       Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2907       Standard_Boolean enlargeVfirst = GlobalEnlargeVfirst, enlargeVlast = GlobalEnlargeVlast;
2908       S->Bounds( u1, u2, v1, v2 );
2909       if (Precision::IsInfinite(u1) || Precision::IsInfinite(u2))
2910         {
2911           du = uf2-uf1;
2912           u1 = uf1-du;
2913           u2 = uf2+du;
2914           enlargeU = Standard_False;
2915         }
2916       else if (S->IsUClosed())
2917         enlargeU = Standard_False;
2918       else
2919         {
2920           viso = S->VIso( vf1 );
2921           GeomAdaptor_Curve gac( viso );
2922           du = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2923           uiso1 = S->UIso( uf1 );
2924           uiso2 = S->UIso( uf2 );
2925           if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex)
2926             enlargeUfirst = Standard_False;
2927           if (BRepOffset_Tool::Gabarit( uiso2 ) <= TolApex)
2928             enlargeUlast = Standard_False;
2929         }
2930       if (Precision::IsInfinite(v1) || Precision::IsInfinite(v2))
2931         {
2932           dv = vf2-vf1;
2933           v1 = vf1-dv;
2934           v2 = vf2+dv;
2935           enlargeV = Standard_False;
2936         }
2937       else if (S->IsVClosed())
2938         enlargeV = Standard_False;
2939       else
2940         {
2941           uiso = S->UIso( uf1 );
2942           GeomAdaptor_Curve gac( uiso );
2943           dv = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2944           viso1 = S->VIso( vf1 );
2945           viso2 = S->VIso( vf2 );
2946           if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex)
2947             {
2948               enlargeVfirst = Standard_False;
2949               IsV1degen = Standard_True;
2950             }
2951           if (BRepOffset_Tool::Gabarit( viso2 ) <= TolApex)
2952             {
2953               enlargeVlast = Standard_False;
2954               IsV2degen = Standard_True;
2955             }
2956         }
2957       Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface( S, u1, u2, v1, v2 );
2958       if (enlargeU)
2959         {
2960           if (enlargeUfirst)
2961             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_False);
2962           if (enlargeUlast)
2963             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_True);
2964         }
2965       if (enlargeV)
2966         {
2967           if (enlargeVfirst)
2968             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_False);
2969           if (enlargeVlast)
2970             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_True);
2971         }
2972       S = aSurf;
2973       S->Bounds( U1, U2, V1, V2 );
2974       SurfaceChange = Standard_True;
2975     }
2976   else if (S->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
2977            S->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
2978     {
2979       Standard_Boolean enlargeU = GlobalEnlargeU, enlargeV = Standard_True;
2980       Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2981       Standard_Boolean enlargeVfirst = GlobalEnlargeVfirst, enlargeVlast = GlobalEnlargeVlast;
2982       if (S->IsUClosed())
2983         enlargeU = Standard_False;
2984       if (S->IsVClosed())
2985         enlargeV = Standard_False;
2986
2987       Standard_Real duf = uf2-uf1, dvf = vf2-vf1;
2988       Standard_Real u1, u2, v1, v2;
2989       S->Bounds( u1, u2, v1, v2 );
2990
2991       Standard_Real du=0., dv=0.;
2992       Handle( Geom_Curve ) uiso, viso, uiso1, uiso2, viso1, viso2;
2993       GeomAdaptor_Curve gac;
2994       if (enlargeU)
2995         {
2996           viso = S->VIso( v1 );
2997           gac.Load( viso );
2998           du = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2999           uiso1 = S->UIso( u1 );
3000           uiso2 = S->UIso( u2 );
3001           if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex)
3002             enlargeUfirst = Standard_False;
3003           if (BRepOffset_Tool::Gabarit( uiso2 ) <= TolApex)
3004             enlargeUlast = Standard_False;
3005         }
3006       if (enlargeV)
3007         {
3008           uiso = S->UIso( u1 );
3009           gac.Load( uiso );
3010           dv = GCPnts_AbscissaPoint::Length( gac ) / coeff;
3011           viso1 = S->VIso( v1 );
3012           viso2 = S->VIso( v2 );
3013           if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex)
3014             {
3015               enlargeVfirst = Standard_False;
3016               IsV1degen = Standard_True;
3017             }
3018           if (BRepOffset_Tool::Gabarit( viso2 ) <= TolApex)
3019             {
3020               enlargeVlast = Standard_False;
3021               IsV2degen = Standard_True;
3022             }
3023         }
3024
3025       Handle(Geom_BoundedSurface) aSurf = Handle(Geom_BoundedSurface)::DownCast (S);
3026       if (enlargeU)
3027         {
3028           if (enlargeUfirst && uf1-u1 < duf)
3029             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_False);
3030           if (enlargeUlast && u2-uf2 < duf)
3031             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_True);
3032         }
3033       if (enlargeV)
3034         {
3035           if (enlargeVfirst && vf1-v1 < dvf)
3036             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_False);
3037           if (enlargeVlast && v2-vf2 < dvf)
3038             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_True);
3039         }
3040       S = aSurf;
3041
3042       S->Bounds( U1, U2, V1, V2 );
3043       SurfaceChange = Standard_True;
3044     }
3045 //  else if (S->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
3046 //         S->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface)) {
3047 //    S->Bounds(U1,U2,V1,V2);
3048 //  }
3049   else { 
3050     Standard_Real UU1,UU2,VV1,VV2;
3051     S->Bounds(UU1,UU2,VV1,VV2);
3052     // Pas d extension au dela des bornes de la surface.
3053     U1 = Max(UU1,U1);    
3054     V1 = Max(VV1,V1);
3055     U2 = Min(UU2,U2);    
3056     V2 = Min(VV2,V2);
3057   }
3058   return SurfaceChange;
3059 }
3060
3061 //=======================================================================
3062 //function : UpDatePCurve
3063 //purpose  :  Mise a jour des pcurves de F sur la surface de de BF.
3064 //            F and BF has to be FORWARD,
3065 //=======================================================================
3066
3067 static void UpdatePCurves (const TopoDS_Face& F,
3068                                  TopoDS_Face& BF)
3069 {
3070   Standard_Real   f,l;
3071   Standard_Integer i;
3072   BRep_Builder    B;
3073   TopTools_IndexedMapOfShape Emap;
3074   Handle(Geom2d_Curve) NullPCurve;
3075
3076   TopExp::MapShapes( F, TopAbs_EDGE, Emap );
3077   
3078   for (i = 1; i <= Emap.Extent(); i++)
3079     {
3080       TopoDS_Edge CE = TopoDS::Edge( Emap(i) );
3081       CE.Orientation( TopAbs_FORWARD );
3082       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface( CE, F, f, l );
3083       if (!C2.IsNull())
3084         {
3085           if (BRep_Tool::IsClosed( CE, F ))
3086             {
3087               CE.Reverse();
3088               Handle(Geom2d_Curve) C2R = BRep_Tool::CurveOnSurface( CE, F, f, l );
3089               B.UpdateEdge( CE, NullPCurve, NullPCurve, F, BRep_Tool::Tolerance(CE) );
3090               B.UpdateEdge( CE, C2, C2R, BF, BRep_Tool::Tolerance(CE) );
3091             }
3092           else
3093             {
3094               B.UpdateEdge( CE, NullPCurve, F, BRep_Tool::Tolerance(CE) );
3095               B.UpdateEdge( CE, C2, BF, BRep_Tool::Tolerance(CE) );
3096             }
3097
3098           B.Range(CE,f,l);
3099         }
3100     }
3101 }
3102
3103 //=======================================================================
3104 //function :CompactUVBounds
3105 //purpose  : 
3106 //=======================================================================
3107
3108 static void CompactUVBounds (const TopoDS_Face& F,
3109                                  Standard_Real& UMin,
3110                                  Standard_Real& UMax,
3111                                  Standard_Real& VMin,
3112                                  Standard_Real& VMax)
3113 {
3114   // Calcul serre pour que les bornes ne couvrent pas plus d une periode
3115   Standard_Real U1,U2;
3116   Standard_Real N = 33;
3117   Bnd_Box2d B;
3118   
3119   TopExp_Explorer exp;  
3120   for (exp.Init(F, TopAbs_EDGE); exp.More(); exp.Next()) {
3121     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3122     BRepAdaptor_Curve2d C(E,F);
3123     BRep_Tool::Range(E,U1,U2);
3124     gp_Pnt2d P;
3125     Standard_Real U  = U1;
3126     Standard_Real DU = (U2-U1)/(N-1);
3127     for (Standard_Integer j=1;j<N;j++) {
3128       C.D0(U,P);
3129       U+=DU;
3130       B.Add(P);
3131     }
3132     C.D0(U2,P);
3133     B.Add(P);
3134   }
3135   B.Get(UMin,VMin,UMax,VMax);
3136 }
3137
3138 //=======================================================================
3139 //function : CheckBounds
3140 //purpose  : 
3141 //=======================================================================
3142
3143 void BRepOffset_Tool::CheckBounds(const TopoDS_Face& F,
3144                                   const BRepOffset_Analyse& Analyse,
3145                                   Standard_Boolean& enlargeU,
3146                                   Standard_Boolean& enlargeVfirst,
3147                                   Standard_Boolean& enlargeVlast)
3148 {
3149   enlargeU = Standard_True;
3150   enlargeVfirst = Standard_True; enlargeVlast = Standard_True;
3151
3152   Standard_Integer Ubound = 0, Vbound = 0;
3153   Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
3154   Standard_Real Vfirst = RealLast(), Vlast = RealFirst();
3155
3156   Standard_Real UF1,UF2,VF1,VF2;
3157   CompactUVBounds(F,UF1,UF2,VF1,VF2);
3158
3159   Handle(Geom_Surface) theSurf = BRep_Tool::Surface(F);
3160   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3161     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (theSurf)->BasisSurface();
3162
3163   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
3164       theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution) ||
3165       theSurf->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
3166       theSurf->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
3167     {
3168       TopExp_Explorer Explo(F, TopAbs_EDGE);
3169       for (; Explo.More(); Explo.Next())
3170         {
3171           const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
3172           const BRepOffset_ListOfInterval& L = Analyse.Type(anEdge);
3173           if (!L.IsEmpty() || BRep_Tool::Degenerated(anEdge))
3174             {
3175               BRepOffset_Type OT = L.First().Type();
3176               if (OT == BRepOffset_Tangent || BRep_Tool::Degenerated(anEdge))
3177                 {
3178                   Standard_Real fpar, lpar;
3179                   Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, F, fpar, lpar);
3180                   if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
3181                     aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (aCurve)->BasisCurve();
3182                   
3183                   Handle(Geom2d_Line) theLine;
3184                   if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_Line))
3185                     theLine = Handle(Geom2d_Line)::DownCast (aCurve);
3186                   else if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BezierCurve) ||
3187                            aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BSplineCurve))
3188                     {
3189                       Standard_Real newFpar, newLpar, deviation;
3190                       theLine = ShapeCustom_Curve2d::ConvertToLine2d(aCurve, fpar, lpar, Precision::Confusion(),
3191                                                                      newFpar, newLpar, deviation);
3192                     }
3193
3194                   if (!theLine.IsNull())
3195                     {
3196                       gp_Dir2d theDir = theLine->Direction();
3197                       if (theDir.IsParallel( gp::DX2d(), Precision::Angular() ))
3198                         {
3199                           Vbound++;
3200                           if (BRep_Tool::Degenerated(anEdge))
3201                             {
3202                               if (Abs(theLine->Location().Y() - VF1) <= Precision::Confusion())
3203                                 enlargeVfirst = Standard_False;
3204                               else //theLine->Location().Y() is near VF2
3205                                 enlargeVlast  = Standard_False;
3206                             }
3207                           else
3208                             {
3209                               if (theLine->Location().Y() < Vfirst)
3210                                 Vfirst = theLine->Location().Y();
3211                               if (theLine->Location().Y() > Vlast)
3212                                 Vlast  = theLine->Location().Y();
3213                             }
3214                         }
3215                       else if (theDir.IsParallel( gp::DY2d(), Precision::Angular() ))
3216                         {
3217                           Ubound++;
3218                           if (theLine->Location().X() < Ufirst)
3219                             Ufirst = theLine->Location().X();
3220                           if (theLine->Location().X() > Ulast)
3221                             Ulast  = theLine->Location().X();
3222                         }
3223                     }
3224                 }
3225             }
3226         }
3227     }
3228
3229   if (Ubound >= 2 || Vbound >= 2)
3230     {
3231       if (Ubound >= 2 &&
3232           Abs(UF1-Ufirst) <= Precision::Confusion() &&
3233           Abs(UF2-Ulast)  <= Precision::Confusion())
3234         enlargeU = Standard_False;
3235       if (Vbound >= 2 &&
3236           Abs(VF1-Vfirst) <= Precision::Confusion() &&
3237           Abs(VF2-Vlast)  <= Precision::Confusion())
3238         {
3239           enlargeVfirst = Standard_False;
3240           enlargeVlast  = Standard_False;
3241         }
3242     }
3243 }
3244
3245 //=======================================================================
3246 //function : EnLargeFace
3247 //purpose  : 
3248 //=======================================================================
3249
3250 Standard_Boolean BRepOffset_Tool::EnLargeFace 
3251 (const TopoDS_Face&       F,
3252  TopoDS_Face&             BF,
3253  const Standard_Boolean   CanExtentSurface,
3254  const Standard_Boolean   UpdatePCurve,
3255  const Standard_Boolean   enlargeU,
3256  const Standard_Boolean   enlargeVfirst,
3257  const Standard_Boolean   enlargeVlast)
3258 {
3259   //---------------------------
3260   // extension de la geometrie.
3261   //---------------------------
3262   TopLoc_Location       L;
3263   Handle (Geom_Surface) S = BRep_Tool::Surface(F,L);
3264   Standard_Real         UU1,VV1,UU2,VV2;
3265   Standard_Boolean      isVV1degen = Standard_False, isVV2degen = Standard_False;
3266   Standard_Real         US1,VS1,US2,VS2;
3267   Standard_Real         UF1,VF1,UF2,VF2;
3268   Standard_Boolean      SurfaceChange = Standard_False;
3269
3270   if (S->IsUPeriodic() || S->IsVPeriodic()) {
3271     // Calcul serre pour que les bornes ne couvre pas plus d une periode
3272     CompactUVBounds(F,UF1,UF2,VF1,VF2);                                        
3273   }
3274   else {
3275     BRepTools::UVBounds(F,UF1,UF2,VF1,VF2);
3276   }
3277
3278   S->Bounds            (US1,US2,VS1,VS2);
3279   UU1 = VV1 = - TheInfini;
3280   UU2 = VV2 =   TheInfini;
3281   
3282   if (CanExtentSurface) {
3283     SurfaceChange = EnlargeGeometry( S, UU1, UU2, VV1, VV2, isVV1degen, isVV2degen, UF1, UF2, VF1, VF2,
3284                                      enlargeU, enlargeVfirst, enlargeVlast );
3285   }
3286   else {
3287     UU1 = Max(US1,UU1); UU2 = Min(UU2,US2); 
3288     VV1 = Max(VS1,VV1); VV2 = Min(VS2,VV2);
3289   }
3290
3291   if (S->IsUPeriodic()) {
3292     Standard_Real    Period = S->UPeriod(); 
3293     Standard_Real    Delta  = Period - (UF2 - UF1);
3294     Standard_Real    alpha  = 0.1;
3295     UU1 = UF1 - alpha*Delta; UU2 = UF2 + alpha*Delta;
3296     if ((UU2 - UU1) > Period) {
3297       UU2 = UU1 + Period;
3298     }
3299   }
3300   if (S->IsVPeriodic()) {
3301     Standard_Real    Period = S->VPeriod(); 
3302     Standard_Real    Delta  = Period - (VF2 - VF1);
3303     Standard_Real    alpha  = 0.1;
3304     VV1 = VF1 - alpha*Delta; VV2 = VF2 + alpha*Delta;
3305     if ((VV2 - VV1) > Period) {
3306       VV2 = VV1 + Period;
3307     }
3308   }
3309
3310   //Special treatment for conical surfaces
3311   Handle(Geom_Surface) theSurf = S;
3312   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3313     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
3314   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
3315     {
3316       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
3317       gp_Cone theCone = ConicalS->Cone();
3318       gp_Pnt theApex = theCone.Apex();
3319       Standard_Real Uapex, Vapex;
3320       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
3321       if (VV1 < Vapex && Vapex < VV2)
3322         {
3323           //consider that VF1 and VF2 are on the same side from apex
3324           Standard_Real TolApex = 1.e-5;
3325           if (Vapex - VF1 >= TolApex ||
3326               Vapex - VF2 >= TolApex)   //if (VF1 < Vapex || VF2 < Vapex)
3327             VV2 = Vapex;
3328           else
3329             VV1 = Vapex;
3330         }
3331     }
3332
3333   if (!enlargeU)
3334     {
3335       UU1 = UF1; UU2 = UF2;
3336     }
3337   if (!enlargeVfirst)
3338     VV1 = VF1;
3339   if (!enlargeVlast)
3340     VV2 = VF2;
3341
3342   MakeFace(S,UU1,UU2,VV1,VV2,isVV1degen,isVV2degen,BF);
3343   BF.Location(L);
3344 /*
3345   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
3346     BRep_Builder B;
3347     //----------------------------------------------------------------
3348     // utile pour les bouchons on ne doit pas changer leur geometrie.
3349     // (Ce que fait BRepLib_MakeFace si S est restreinte).
3350     // On remet S et on update les pcurves.
3351     //----------------------------------------------------------------
3352     TopExp_Explorer exp;
3353     exp.Init(BF,TopAbs_EDGE);
3354     Standard_Real f=0.,l=0.;
3355     for (; exp.More(); exp.Next()) {
3356       TopoDS_Edge   CE  = TopoDS::Edge(exp.Current());
3357       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(CE,BF,f,l); 
3358       B.UpdateEdge (CE,C2,S,L,BRep_Tool::Tolerance(CE));
3359     }    
3360     B.UpdateFace(BF,S,L,BRep_Tool::Tolerance(F)); 
3361   }
3362 */  
3363   if (SurfaceChange && UpdatePCurve) {
3364     TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3365     UpdatePCurves(TopoDS::Face(aLocalFace),BF);
3366     //UpdatePCurves(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),BF);
3367     BRep_Builder BB;
3368     BB.UpdateFace( F, S, L, BRep_Tool::Tolerance(F) );
3369   }
3370
3371   BF.Orientation(F.Orientation());
3372   return SurfaceChange;
3373 }
3374
3375 //=======================================================================
3376 //function : TryParameter
3377 //purpose  : 
3378 //=======================================================================
3379
3380 static Standard_Boolean TryParameter (const TopoDS_Edge& OE,
3381                                       TopoDS_Vertex&     V,
3382                                       const TopoDS_Edge& NE,
3383                                       Standard_Real      TolConf)
3384 {
3385   BRepAdaptor_Curve OC(OE);
3386   BRepAdaptor_Curve NC(NE);
3387   Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
3388   Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
3389   Standard_Real U = 0.;
3390   gp_Pnt           P  = BRep_Tool::Pnt(V);
3391   Standard_Boolean OK = Standard_False;
3392
3393   if (P.Distance(OC.Value(Of)) < TolConf) {
3394     if (Of > Nf && Of < Nl  && P.Distance(NC.Value(Of)) < TolConf) {
3395       OK = Standard_True;
3396       U    = Of;
3397     }
3398   }
3399   if (P.Distance(OC.Value(Ol)) < TolConf) {
3400     if (Ol > Nf && Ol < Nl  && P.Distance(NC.Value(Ol)) < TolConf) {
3401       OK = Standard_True;
3402       U    = Ol;
3403     }
3404   }
3405   if (OK) {
3406     BRep_Builder B;
3407     TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
3408     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
3409 //    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
3410     aLocalShape = V.Oriented(TopAbs_INTERNAL);
3411     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
3412                    U,NE,BRep_Tool::Tolerance(NE));
3413 //    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
3414 //                 U,NE,BRep_Tool::Tolerance(NE));
3415   }
3416   return OK;  
3417 }
3418
3419 //=======================================================================
3420 //function : 
3421 //purpose  : 
3422 //=======================================================================
3423
3424 void BRepOffset_Tool::MapVertexEdges (const TopoDS_Shape& S,
3425                                       TopTools_DataMapOfShapeListOfShape& MEV)
3426 {
3427   TopExp_Explorer      exp;
3428   exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3429   TopTools_MapOfShape  DejaVu;
3430   for ( ; exp.More(); exp.Next()) {
3431     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3432     if (DejaVu.Add(E)) {
3433       TopoDS_Vertex     V1,V2;
3434       TopExp::Vertices (E,V1,V2);
3435       if (!MEV.IsBound(V1)) {
3436         TopTools_ListOfShape empty;
3437         MEV.Bind(V1,empty);
3438       }
3439       MEV(V1).Append(E);
3440       if (!V1.IsSame(V2)) {
3441         if (!MEV.IsBound(V2)) {
3442           TopTools_ListOfShape empty;
3443           MEV.Bind(V2,empty);
3444         }
3445         MEV(V2).Append(E);
3446       }
3447     }
3448   }
3449 }
3450
3451 //=======================================================================
3452 //function : 
3453 //purpose  : 
3454 //=======================================================================
3455
3456 void BRepOffset_Tool::BuildNeighbour (const TopoDS_Wire& W,
3457                                       const TopoDS_Face& F,
3458                                       TopTools_DataMapOfShapeShape& NOnV1,
3459                                       TopTools_DataMapOfShapeShape& NOnV2)
3460 {
3461   TopoDS_Vertex V1,V2,VP1,VP2,FV1,FV2;
3462   TopoDS_Edge   CurE,FirstE,PrecE;
3463   BRepTools_WireExplorer         wexp;
3464   
3465   TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3466   TopoDS_Shape aLocalWire = W.Oriented(TopAbs_FORWARD);
3467   wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
3468 //  wexp.Init(TopoDS::Wire(W.Oriented(TopAbs_FORWARD)),
3469 //          TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
3470   CurE = FirstE = PrecE = wexp.Current();
3471   TopExp::Vertices(CurE,V1,V2);
3472   FV1 = VP1 = V1; FV2 = VP2 = V2;
3473   wexp.Next();
3474   while (wexp.More()) {
3475     CurE = wexp.Current();
3476     TopExp::Vertices(CurE,V1,V2);
3477     if (V1.IsSame(VP1)) { NOnV1.Bind(PrecE,CurE); NOnV1.Bind(CurE,PrecE);}
3478     if (V1.IsSame(VP2)) { NOnV2.Bind(PrecE,CurE); NOnV1.Bind(CurE,PrecE);}
3479     if (V2.IsSame(VP1)) { NOnV1.Bind(PrecE,CurE); NOnV2.Bind(CurE,PrecE);}
3480     if (V2.IsSame(VP2)) { NOnV2.Bind(PrecE,CurE); NOnV2.Bind(CurE,PrecE);}
3481     PrecE = CurE;
3482     VP1 = V1; VP2 = V2;
3483     wexp.Next();
3484   }
3485   if (V1.IsSame(FV1)) { NOnV1.Bind(FirstE,CurE); NOnV1.Bind(CurE,FirstE);}
3486   if (V1.IsSame(FV2)) { NOnV2.Bind(FirstE,CurE); NOnV1.Bind(CurE,FirstE);}
3487   if (V2.IsSame(FV1)) { NOnV1.Bind(FirstE,CurE); NOnV2.Bind(CurE,FirstE);}
3488   if (V2.IsSame(FV2)) { NOnV2.Bind(FirstE,CurE); NOnV2.Bind(CurE,FirstE);}
3489 }
3490
3491 //=======================================================================
3492 //function : ExtentFace
3493 //purpose  : 
3494 //=======================================================================
3495
3496 void BRepOffset_Tool::ExtentFace (const TopoDS_Face&            F,
3497                                   TopTools_DataMapOfShapeShape& ConstShapes,
3498                                   TopTools_DataMapOfShapeShape& ToBuild,
3499                                   const TopAbs_State            Side,
3500                                   const Standard_Real           TolConf,
3501                                   TopoDS_Face&                  NF)
3502 {
3503 #ifdef DRAW
3504   if (AffichInter) {
3505     char name[256];
3506     sprintf(name,"FTE_%d",NbFTE++);
3507     DBRep::Set(name,F);
3508   }
3509 #endif
3510   
3511   TopExp_Explorer                    exp,exp2;
3512   TopTools_DataMapOfShapeShape       Build;
3513   TopTools_DataMapOfShapeShape       Extent;
3514   TopoDS_Edge                        FirstE,PrecE,CurE,NE;
3515   BRep_Builder B;
3516   TopoDS_Face  EF;
3517
3518   // Construction de la boite englobante de la face a etendre et des bouchons pour
3519   // limiter les extensions.
3520   //Bnd_Box ContextBox;
3521   //BRepBndLib::Add(F,B);
3522   //TopTools_DataMapIteratorOfDataMapOfShape itTB(ToBuild);
3523   //for (; itTB.More(); itTB.Next()) {
3524   //BRepBndLib::Add(TopBuild.Value(), ContextBox);
3525   //}
3526
3527    
3528   Standard_Boolean SurfaceChange;
3529   SurfaceChange = EnLargeFace (F,EF,Standard_True);
3530
3531   TopoDS_Shape aLocalShape = EF.EmptyCopied();
3532   NF = TopoDS::Face(aLocalShape);
3533 //  NF = TopoDS::Face(EF.EmptyCopied());
3534   NF.Orientation(TopAbs_FORWARD);
3535
3536   if (SurfaceChange) {
3537     //------------------------------------------------
3538     // Mise a jour des pcurves sur la surface de base.
3539     //------------------------------------------------
3540     TopoDS_Face Fforward = F;
3541     Fforward.Orientation(TopAbs_FORWARD);
3542     TopTools_IndexedMapOfShape Emap;
3543     TopExp::MapShapes( Fforward, TopAbs_EDGE, Emap );
3544     Standard_Real f,l;
3545     for (Standard_Integer i = 1; i <= Emap.Extent(); i++) {
3546       TopoDS_Edge   CE  = TopoDS::Edge( Emap(i) );
3547       CE.Orientation(TopAbs_FORWARD);
3548       TopoDS_Edge   Ecs; //patch
3549       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(CE,Fforward,f,l);
3550       if (!C2.IsNull()) {
3551         if (ConstShapes.IsBound(CE)) {
3552           Ecs = TopoDS::Edge(ConstShapes(CE));
3553           BRep_Tool::Range(Ecs,f,l);
3554         }
3555         if (BRep_Tool::IsClosed(CE,Fforward))  {
3556           TopoDS_Shape aLocalShapeReversedCE = CE.Reversed();
3557           Handle(Geom2d_Curve) C2R = 
3558             BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShapeReversedCE),Fforward,f,l);
3559 //        Handle(Geom2d_Curve) C2R = 
3560 //          BRep_Tool::CurveOnSurface(TopoDS::Edge(CE.Reversed()),F,f,l);
3561           B.UpdateEdge (CE,C2,C2R,EF,BRep_Tool::Tolerance(CE));
3562           if (! Ecs.IsNull())
3563             B.UpdateEdge (Ecs,C2,C2R,EF,BRep_Tool::Tolerance(CE));
3564         }
3565         else {
3566           B.UpdateEdge (CE,C2,EF,BRep_Tool::Tolerance(CE));
3567           if (! Ecs.IsNull())
3568             B.UpdateEdge (Ecs,C2,EF,BRep_Tool::Tolerance(CE));
3569         }
3570         B.Range(CE,f,l);
3571         if (! Ecs.IsNull())
3572           B.Range(Ecs,f,l);
3573       }
3574     }
3575   }
3576   
3577   for (exp.Init(F.Oriented(TopAbs_FORWARD),TopAbs_WIRE); 
3578        exp.More();
3579        exp.Next()) {
3580     const TopoDS_Wire& W = TopoDS::Wire(exp.Current());
3581     TopTools_DataMapOfShapeListOfShape MVE; // Vertex -> Edges incidentes.
3582     TopTools_DataMapOfShapeShape       NOnV1;
3583     TopTools_DataMapOfShapeShape       NOnV2;
3584
3585     MapVertexEdges (W,MVE);
3586     BuildNeighbour (W,F,NOnV1,NOnV2);
3587     
3588     TopTools_ListOfShape LInt1,LInt2;
3589     TopoDS_Face          StopFace;
3590     //------------------------------------------------
3591     // Construction edges
3592     //------------------------------------------------
3593     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
3594          exp2.More(); exp2.Next()) {
3595       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3596       if (ConstShapes.IsBound(E)) ToBuild.UnBind(E);
3597       if (ToBuild.IsBound(E)) {
3598         TopTools_ListOfShape LOE;
3599         LOE.Append(E);
3600         BRepOffset_Tool::TryProject (TopoDS::Face(ToBuild(E)),
3601                                      EF,LOE,LInt2,LInt1,Side,TolConf);
3602         if (!LInt1.IsEmpty()) 
3603           ToBuild.UnBind(E);
3604       }
3605     }
3606
3607     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
3608          exp2.More(); exp2.Next()) {
3609       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3610       if (ConstShapes.IsBound(E)) ToBuild.UnBind(E);
3611       if (ToBuild.IsBound(E)) {
3612         EnLargeFace(TopoDS::Face(ToBuild(E)),StopFace,Standard_False);
3613         BRepOffset_Tool::Inter3D (EF,StopFace,LInt1,LInt2,Side,E,Standard_True);
3614         // No intersection, it may happen for example for a chosen (non-offseted) planar face and 
3615         // its neighbour offseted cylindrical face, if the offset is directed so that 
3616         // the radius of the cylinder becomes smaller.
3617         if (LInt1.IsEmpty())
3618           continue;  
3619         if (LInt1.Extent() > 1) { 
3620           // l intersection est en plusieurs edges (franchissement de couture)
3621           SelectEdge (F,EF,E,LInt1);
3622         }
3623         NE = TopoDS::Edge(LInt1.First());
3624         Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &NE.TShape());
3625         TE->Tolerance( TE->Tolerance()*10. ); //????
3626         if (NE.Orientation() == E.Orientation()) {
3627           Build.Bind(E,NE.Oriented(TopAbs_FORWARD));
3628         }
3629         else {
3630           Build.Bind(E,NE.Oriented(TopAbs_REVERSED));
3631         }
3632         const TopoDS_Edge& EOnV1 = TopoDS::Edge(NOnV1(E));
3633         if (!ToBuild    .IsBound(EOnV1) && 
3634             !ConstShapes.IsBound(EOnV1) && 
3635             !Build      .IsBound(EOnV1)) {
3636           ExtentEdge (F,EF,EOnV1,NE);
3637           Build.Bind (EOnV1,NE.Oriented(TopAbs_FORWARD));
3638         }
3639         const TopoDS_Edge& EOnV2 = TopoDS::Edge(NOnV2(E));
3640         if (!ToBuild    .IsBound(EOnV2) && 
3641             !ConstShapes.IsBound(EOnV2) && 
3642             !Build      .IsBound(EOnV2)) {
3643           ExtentEdge (F,EF,EOnV2,NE);
3644           Build.Bind (EOnV2,NE.Oriented (TopAbs_FORWARD));
3645         }
3646       }
3647     }
3648
3649     //------------------------------------------------
3650     // Construction Vertex.
3651     //------------------------------------------------
3652     TopTools_ListOfShape LV;
3653     Standard_Real        f,l;
3654     TopoDS_Edge          ERef;
3655     TopoDS_Vertex        V1,V2;
3656
3657     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exp2.More(); exp2.Next())
3658     {
3659       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3660       TopExp::Vertices (E,V1,V2);
3661       BRep_Tool::Range (E,f,l);
3662       TopoDS_Vertex V;
3663       if (Build.IsBound(E))
3664       {
3665         const TopoDS_Edge& NEOnV1 = TopoDS::Edge(NOnV1(E));
3666         if (Build.IsBound(NEOnV1) && (ToBuild.IsBound(E) || ToBuild.IsBound(NEOnV1)))
3667         {
3668           if (E.IsSame(NEOnV1))
3669             V = TopExp::FirstVertex(TopoDS::Edge(Build(E)));
3670           else
3671           {
3672             //---------------
3673             // intersection.
3674             //---------------
3675             if (!Build.IsBound(V1))
3676             {
3677               Inter2d (EF,TopoDS::Edge(Build(E)), TopoDS::Edge(Build(NEOnV1)),LV,/*TolConf*/Precision::Confusion());
3678               
3679               if(!LV.IsEmpty())
3680               {
3681                 if (Build(E).Orientation() == TopAbs_FORWARD)
3682                 {
3683                   V = TopoDS::Vertex(LV.First());
3684                 }
3685                 else
3686                 {
3687                   V = TopoDS::Vertex(LV.Last());
3688                 }
3689               }
3690               else
3691               {
3692                 return;
3693               }
3694             }
3695             else
3696             {
3697               V = TopoDS::Vertex(Build(V1));
3698               if (MVE (V1).Extent() > 2)
3699               {
3700                 V.Orientation(TopAbs_FORWARD);
3701                 if (Build(E).Orientation() == TopAbs_REVERSED)
3702                   V.Orientation(TopAbs_REVERSED);
3703
3704                 ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3705               }
3706             }
3707           }
3708         }
3709         else
3710         {
3711           //------------
3712           //projection
3713           //------------
3714           V = V1;
3715           if (ConstShapes.IsBound(V1)) V = TopoDS::Vertex(ConstShapes(V1));
3716           V.Orientation(TopAbs_FORWARD);
3717           if (Build(E).Orientation() == TopAbs_REVERSED)
3718             V.Orientation(TopAbs_REVERSED);
3719           if (!TryParameter    (E,V,TopoDS::Edge(Build(E)),TolConf))
3720             ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3721         }
3722
3723         ConstShapes.Bind(V1,V);
3724         Build.Bind      (V1,V);
3725         const TopoDS_Edge& NEOnV2 = TopoDS::Edge(NOnV2(E));
3726         if (Build.IsBound(NEOnV2) && (ToBuild.IsBound(E) || ToBuild.IsBound(NEOnV2)))
3727         {
3728           if (E.IsSame(NEOnV2))
3729             V = TopExp::LastVertex(TopoDS::Edge(Build(E)));
3730           else
3731           {
3732             //--------------
3733             // intersection.
3734             //---------------
3735
3736             if (!Build.IsBound(V2))
3737             {
3738               Inter2d (EF,TopoDS::Edge(Build(E)), TopoDS::Edge(Build(NEOnV2)),LV,/*TolConf*/Precision::Confusion());
3739
3740               if(!LV.IsEmpty())
3741               {
3742                 if (Build(E).Orientation() == TopAbs_FORWARD)
3743                 {
3744                   V = TopoDS::Vertex(LV.Last());
3745                 }
3746                 else
3747                 {
3748                   V = TopoDS::Vertex(LV.First());
3749                 }
3750               }
3751               else
3752               {
3753                 return;
3754               }
3755             }
3756             else
3757             {
3758               V = TopoDS::Vertex(Build(V2));
3759               if (MVE (V2).Extent() > 2)
3760               {
3761                 V.Orientation(TopAbs_REVERSED);
3762                 if (Build(E).Orientation() == TopAbs_REVERSED)
3763                   V.Orientation(TopAbs_FORWARD);
3764
3765                 ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3766               }
3767             }
3768           }
3769         }
3770         else
3771         {
3772           //------------
3773           //projection
3774           //------------
3775           V = V2;
3776           if (ConstShapes.IsBound(V2))
3777             V = TopoDS::Vertex(ConstShapes(V2));
3778           V.Orientation(TopAbs_REVERSED);       
3779           if (Build(E).Orientation() == TopAbs_REVERSED)
3780             V.Orientation(TopAbs_FORWARD);
3781           if (!TryParameter (E,V,TopoDS::Edge(Build(E)),TolConf))
3782             ProjectVertexOnEdge(V,TopoDS::Edge(Build(E)),TolConf);
3783         }
3784         ConstShapes.Bind(V2,V);
3785         Build.Bind(V2,V);
3786       }
3787     }
3788     
3789     TopoDS_Wire        NW;
3790     TopoDS_Vertex      NV1,NV2;
3791     TopAbs_Orientation Or;
3792     Standard_Real      U1,U2;
3793     Standard_Real      eps = Precision::Confusion();
3794
3795 #ifdef OCCT_DEBUG
3796     TopLoc_Location    L;
3797 #endif
3798     B.MakeWire(NW);
3799
3800     //-----------------
3801     // Reconstruction.
3802     //-----------------
3803     for (exp2.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
3804          exp2.More(); exp2.Next()) {
3805       const TopoDS_Edge& E = TopoDS::Edge(exp2.Current());
3806       TopExp::Vertices (E,V1,V2);
3807       if (Build.IsBound(E)) {
3808         NE = TopoDS::Edge(Build(E));
3809         BRep_Tool::Range(NE,f,l);
3810         Or = NE.Orientation();
3811         //-----------------------------------------------------
3812         // Copy pour virer les vertex deja sur la nouvelle edge.
3813         //-----------------------------------------------------
3814         NV1 = TopoDS::Vertex(ConstShapes(V1));
3815         NV2 = TopoDS::Vertex(ConstShapes(V2));
3816
3817         TopoDS_Shape aLocalVertexOrientedNV1 = NV1.Oriented(TopAbs_INTERNAL);
3818         TopoDS_Shape aLocalEdge   = NE.Oriented(TopAbs_INTERNAL);
3819         
3820         U1 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalVertexOrientedNV1),
3821                                   TopoDS::Edge  (aLocalEdge));
3822         aLocalVertexOrientedNV1 = NV2.Oriented(TopAbs_INTERNAL);
3823         aLocalEdge   = NE.Oriented(TopAbs_FORWARD);
3824         U2 = BRep_Tool::Parameter (TopoDS::Vertex(aLocalVertexOrientedNV1),TopoDS::Edge  (aLocalEdge));
3825 //      U1 = BRep_Tool::Parameter
3826 //        (TopoDS::Vertex(NV1.Oriented(TopAbs_INTERNAL)),
3827 //         TopoDS::Edge  (NE .Oriented(TopAbs_FORWARD)));
3828 //      U2 = BRep_Tool::Parameter
3829 //        (TopoDS::Vertex(NV2.Oriented(TopAbs_INTERNAL)),
3830 //         TopoDS::Edge  (NE.Oriented(TopAbs_FORWARD)));
3831         aLocalEdge = NE.EmptyCopied();
3832         NE = TopoDS::Edge(aLocalEdge);
3833         NE.Orientation(TopAbs_FORWARD);
3834         if (NV1.IsSame(NV2))
3835           {
3836             //--------------
3837             // edge ferme.
3838             //--------------
3839             if (Or == TopAbs_FORWARD) {U1 = f; U2 = l;}
3840             else                      {U1 = l; U2 = f;}
3841             if (Or == TopAbs_FORWARD)
3842               {
3843                 if (U1 > U2)
3844                   {
3845                     if (Abs(U1-l) < eps) U1 = f;
3846                     if (Abs(U2-f) < eps) U2 = l;            
3847                   }
3848                 TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3849                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3850                 aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3851                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3852 //              B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3853 //              B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3854                 B.Range(NE,U1,U2);
3855                 ConstShapes.Bind(E,NE);
3856                 NE.Orientation(E.Orientation());
3857               }
3858             else
3859               {
3860                 if (U2 > U1)
3861                   {
3862                     if (Abs(U2-l) < eps) U2 = f;
3863                     if (Abs(U1-f) < eps) U1 = l;            
3864                   }
3865                 TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3866                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3867                 aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3868                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3869 //              B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3870 //              B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3871                 B.Range(NE,U2,U1);
3872                 ConstShapes.Bind(E,NE.Oriented(TopAbs_REVERSED));
3873                 NE.Orientation(TopAbs::Reverse(E.Orientation()));
3874               }
3875           }
3876         else
3877           {
3878             //-------------------
3879             // edge is not ferme.
3880             //-------------------
3881             if (Or == TopAbs_FORWARD) {
3882               if (U1 > U2) {
3883                 TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3884                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3885                 aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3886                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3887 //              B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3888 //              B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3889                 B.Range(NE,U2,U1);
3890               }
3891               else
3892                 {
3893                   TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3894                   B.Add (NE,TopoDS::Vertex(aLocalVertex));
3895                   aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3896                   B.Add (NE,TopoDS::Vertex(aLocalVertex));
3897 //                B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3898 //                B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3899                   B.Range(NE,U1,U2);
3900                 }
3901               ConstShapes.Bind(E,NE);
3902               NE.Orientation(E.Orientation());
3903             }
3904             else {
3905               if (U2 > U1) {
3906                 TopoDS_Shape aLocalVertex = NV1.Oriented(TopAbs_FORWARD );
3907                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3908                 aLocalVertex = NV2.Oriented(TopAbs_REVERSED);
3909                 B.Add (NE,TopoDS::Vertex(aLocalVertex));
3910 //              B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_FORWARD )));
3911 //              B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_REVERSED)));
3912                 B.Range(NE,U1,U2);
3913                 ConstShapes.Bind(E,NE);
3914                 NE.Orientation(E.Orientation());
3915               }
3916               else
3917                 {
3918                   TopoDS_Shape aLocalVertex = NV2.Oriented(TopAbs_FORWARD );
3919                   B.Add (NE,TopoDS::Vertex(aLocalVertex));
3920                   aLocalVertex = NV1.Oriented(TopAbs_REVERSED);
3921                   B.Add (NE,TopoDS::Vertex(aLocalVertex));
3922 //                B.Add (NE,TopoDS::Vertex(NV2.Oriented(TopAbs_FORWARD )));
3923 //                B.Add (NE,TopoDS::Vertex(NV1.Oriented(TopAbs_REVERSED)));
3924                   B.Range(NE,U2,U1);
3925                   ConstShapes.Bind(E,NE.Oriented(TopAbs_REVERSED));
3926                   NE.Orientation(TopAbs::Reverse(E.Orientation()));
3927                 }
3928             }
3929           }
3930         Build.UnBind(E);
3931       } // Build.IsBound(E)
3932       else if (ConstShapes.IsBound(E)) { // !Build.IsBound(E)
3933         NE = TopoDS::Edge(ConstShapes(E));      
3934         BuildPCurves(NE,NF);
3935         Or = NE.Orientation();
3936         if (Or == TopAbs_REVERSED) {
3937           NE.Orientation(TopAbs::Reverse(E.Orientation()));
3938         }
3939         else {
3940           NE.Orientation(E.Orientation());
3941         }
3942       }
3943       else {
3944         NE = E;
3945         ConstShapes.Bind(E,NE.Oriented(TopAbs_FORWARD));
3946       }
3947       B.Add(NW,NE);
3948     }
3949     B.Add(NF,NW.Oriented(W.Orientation()));
3950   }
3951   NF.Orientation(F.Orientation());
3952   BRepTools::Update(NF); // Maj des UVPoints
3953   
3954 #ifdef DRAW
3955   if (AffichInter) {
3956     char name[256];
3957     sprintf(name,"FOB_%d",NbFOB++);
3958     DBRep::Set(name,NF);
3959   }
3960 #endif
3961 }
3962   
3963
3964 //=======================================================================
3965 //function : Deboucle3D
3966 //purpose  : 
3967 //=======================================================================
3968
3969 TopoDS_Shape BRepOffset_Tool::Deboucle3D(const TopoDS_Shape& S,
3970                                          const TopTools_MapOfShape& Boundary)
3971 {
3972   return BRepAlgo_Tool::Deboucle3D(S,Boundary);
3973 }
3974
3975 //=======================================================================
3976 //function : IsInOut
3977 //purpose  : 
3978 //=======================================================================
3979
3980 static Standard_Boolean IsInOut (BRepTopAdaptor_FClass2d& FC,
3981                                  Geom2dAdaptor_Curve      AC,
3982                                  const TopAbs_State&      S )
3983 {
3984  Standard_Real Def = 100*Precision::Confusion();
3985  GCPnts_QuasiUniformDeflection QU(AC,Def);
3986  
3987  for (Standard_Integer i = 1; i <= QU.NbPoints(); i++) {
3988    gp_Pnt2d P = AC.Value(QU.Parameter(i));
3989    if (FC.Perform(P) != S) {
3990      return Standard_False;
3991    } 
3992  }
3993  return Standard_True;
3994 }
3995                                   
3996 //=======================================================================
3997 //function : CorrectOrientation
3998 //purpose  : 
3999 //=======================================================================
4000
4001 void BRepOffset_Tool::CorrectOrientation(const TopoDS_Shape&        SI,
4002                                          const TopTools_IndexedMapOfShape& NewEdges,
4003                                          Handle(BRepAlgo_AsDes)&    AsDes,
4004                                          BRepAlgo_Image&            InitOffset,
4005                                          const Standard_Real        Offset)
4006 {
4007
4008   TopExp_Explorer exp;
4009   exp.Init(SI,TopAbs_FACE);
4010   Standard_Real   f=0.,l=0.;
4011
4012   for (; exp.More(); exp.Next()) {
4013
4014     const TopoDS_Face&          FI  = TopoDS::Face(exp.Current());
4015     const TopTools_ListOfShape& LOF = InitOffset.Image(FI);
4016     TopTools_ListIteratorOfListOfShape it(LOF);
4017     for (; it.More(); it.Next()) {
4018       const TopoDS_Face&    OF   = TopoDS::Face(it.Value());
4019       TopTools_ListOfShape& LOE = AsDes->ChangeDescendant(OF);
4020       TopTools_ListIteratorOfListOfShape itE(LOE);
4021
4022       Standard_Boolean YaInt = Standard_False;
4023       for (; itE.More(); itE.Next()) {
4024         const TopoDS_Edge& OE = TopoDS::Edge(itE.Value());
4025         if (NewEdges.Contains(OE)) {YaInt = Standard_True; break;}
4026       }
4027       if (YaInt) {
4028         TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
4029         BRepTopAdaptor_FClass2d FC (TopoDS::Face(aLocalFace),
4030                                     Precision::Confusion());
4031 //      BRepTopAdaptor_FClass2d FC (TopoDS::Face(FI.Oriented(TopAbs_FORWARD)),
4032 //                                  Precision::Confusion());
4033         for (itE.Initialize(LOE); itE.More(); itE.Next()) {
4034           TopoDS_Shape&   OE   = itE.Value();
4035           if (NewEdges.Contains(OE)) {
4036             Handle(Geom2d_Curve) CO2d = 
4037               BRep_Tool::CurveOnSurface(TopoDS::Edge(OE),OF,f,l);
4038             Geom2dAdaptor_Curve  AC(CO2d,f,l);
4039             
4040             if (Offset > 0) {
4041               if (IsInOut(FC,AC,TopAbs_OUT)) OE.Reverse();
4042             }
4043 //          else {
4044 //            if (IsInOut(FC,AC,TopAbs_IN)) OE.Reverse();           
4045 //          }
4046           }
4047         }
4048       }
4049     }
4050   }
4051
4052 }
4053
4054 //=======================================================================
4055 //function : CheckNormals
4056 //purpose  : 
4057 //=======================================================================
4058 Standard_Boolean BRepOffset_Tool::CheckPlanesNormals(const TopoDS_Face& theFace1,
4059                                                      const TopoDS_Face& theFace2,
4060                                                      const Standard_Real theTolAng)
4061 {
4062   BRepAdaptor_Surface aBAS1(theFace1, Standard_False), aBAS2(theFace2, Standard_False);
4063   if (aBAS1.GetType() != GeomAbs_Plane ||
4064       aBAS2.GetType() != GeomAbs_Plane) {
4065     return Standard_False;
4066   }
4067   //
4068   gp_Dir aDN1 = aBAS1.Plane().Position().Direction();
4069   if (theFace1.Orientation() == TopAbs_REVERSED) {
4070     aDN1.Reverse();
4071   }
4072   //
4073   gp_Dir aDN2 = aBAS2.Plane().Position().Direction();
4074   if (theFace2.Orientation() == TopAbs_REVERSED) {
4075     aDN2.Reverse();
4076   }
4077   //
4078   Standard_Real anAngle = aDN1.Angle(aDN2);
4079   return (anAngle < theTolAng);
4080 }
4081
4082 //=======================================================================
4083 //function : PerformPlanes
4084 //purpose  : 
4085 //=======================================================================
4086 void PerformPlanes(const TopoDS_Face& theFace1,
4087                    const TopoDS_Face& theFace2,
4088                    const TopAbs_State theSide,
4089                    TopTools_ListOfShape& theL1,
4090                    TopTools_ListOfShape& theL2)
4091 {
4092   theL1.Clear();
4093   theL2.Clear();
4094   // Intersect the planes using IntTools_FaceFace directly
4095   IntTools_FaceFace aFF;
4096   aFF.SetParameters(Standard_True, Standard_True, Standard_True, Precision::Confusion());
4097   aFF.Perform(theFace1, theFace2);
4098   //
4099   if (!aFF.IsDone()) {
4100     return;
4101   }
4102   //
4103   const IntTools_SequenceOfCurves& aSC = aFF.Lines();
4104   if (aSC.IsEmpty()) {
4105     return;
4106   }
4107   //
4108   // In Plane/Plane intersection only one curve is always produced.
4109   // Make the edge from this section curve.
4110   TopoDS_Edge aE;
4111   {
4112     BRep_Builder aBB;
4113     const IntTools_Curve& aIC = aSC(1);
4114     const Handle(Geom_Curve)& aC3D = aIC.Curve();
4115     aBB.MakeEdge(aE, aC3D, aIC.Tolerance());
4116     // Get bounds of the curve
4117     Standard_Real aTF, aTL;
4118     gp_Pnt aPF, aPL;
4119     aIC.Bounds(aTF, aTL, aPF, aPL);
4120     // Make the bounding vertices
4121     TopoDS_Vertex aVF, aVL;
4122     aBB.MakeVertex(aVF, aPF, aIC.Tolerance());
4123     aBB.MakeVertex(aVL, aPL, aIC.Tolerance());
4124     aVL.Orientation(TopAbs_REVERSED);
4125     // Add vertices to the edge
4126     aBB.Add(aE, aVF);
4127     aBB.Add(aE, aVL);
4128     // Add 2D curves to the edge
4129     aBB.UpdateEdge(aE, aIC.FirstCurve2d(), theFace1, aIC.Tolerance());
4130     aBB.UpdateEdge(aE, aIC.SecondCurve2d(), theFace2, aIC.Tolerance());
4131     // Update range of the new edge
4132     aBB.Range(aE, aTF, aTL);
4133   }
4134   //
4135   // Orient section
4136   TopAbs_Orientation O1, O2;
4137   BRepOffset_Tool::OrientSection(aE, theFace1, theFace2, O1, O2);
4138   if (theSide == TopAbs_OUT) {
4139     O1 = TopAbs::Reverse(O1);
4140     O2 = TopAbs::Reverse(O2);
4141   }
4142   //
4143   BRepLib::SameParameter(aE, Precision::Confusion(), Standard_True);
4144   //
4145   // Add edge to result
4146   theL1.Append(aE.Oriented(O1));
4147   theL2.Append(aE.Oriented(O2));
4148 }
4149
4150 //=======================================================================
4151 //function : IsInf
4152 //purpose  : Checks if the given value is close to infinite (TheInfini)
4153 //=======================================================================
4154 Standard_Boolean IsInf(const Standard_Real theVal)
4155 {
4156   return (theVal > TheInfini*0.9);
4157 }