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