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