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