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