0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / BRepOffset / BRepOffset_Offset.cxx
1 // Created on: 1995-10-19
2 // Created by: Bruno DUMORTIER
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 <Adaptor3d_CurveOnSurface.hxx>
19 #include <Adaptor3d_HCurveOnSurface.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRep_GCurve.hxx>
22 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
23 #include <BRep_ListOfCurveRepresentation.hxx>
24 #include <BRep_TEdge.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepGProp.hxx>
27 #include <BRepLib.hxx>
28 #include <BRepLib_MakeFace.hxx>
29 #include <BRepLib_MakeWire.hxx>
30 #include <BRepOffset.hxx>
31 #include <BRepOffset_Offset.hxx>
32 #include <BRepOffset_Tool.hxx>
33 #include <BRepTools.hxx>
34 #include <ElSLib.hxx>
35 #include <gce_MakePln.hxx>
36 #include <Geom2d_Curve.hxx>
37 #include <Geom2d_Line.hxx>
38 #include <Geom2d_TrimmedCurve.hxx>
39 #include <Geom2dAdaptor_Curve.hxx>
40 #include <Geom2dAdaptor_HCurve.hxx>
41 #include <Geom_Circle.hxx>
42 #include <Geom_ConicalSurface.hxx>
43 #include <Geom_Curve.hxx>
44 #include <Geom_Line.hxx>
45 #include <Geom_OffsetSurface.hxx>
46 #include <Geom_RectangularTrimmedSurface.hxx>
47 #include <Geom_SphericalSurface.hxx>
48 #include <Geom_SurfaceOfLinearExtrusion.hxx>
49 #include <Geom_SurfaceOfRevolution.hxx>
50 #include <Geom_Surface.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <GeomAdaptor_Curve.hxx>
53 #include <GeomAdaptor_HCurve.hxx>
54 #include <GeomAdaptor_HSurface.hxx>
55 #include <GeomAdaptor_Surface.hxx>
56 #include <GeomAPI.hxx>
57 #include <GeomAPI_ExtremaCurveCurve.hxx>
58 #include <GeomAPI_ProjectPointOnCurve.hxx>
59 #include <GeomConvert_ApproxSurface.hxx>
60 #include <GeomFill_Pipe.hxx>
61 #include <GeomLib.hxx>
62 #include <GeomProjLib.hxx>
63 #include <gp.hxx>
64 #include <gp_Ax3.hxx>
65 #include <gp_Cylinder.hxx>
66 #include <gp_Lin.hxx>
67 #include <gp_Pnt2d.hxx>
68 #include <gp_Torus.hxx>
69 #include <GProp_GProps.hxx>
70 #include <Precision.hxx>
71 #include <ShapeFix_Shape.hxx>
72 #include <Standard_ConstructionError.hxx>
73 #include <TopExp.hxx>
74 #include <TopExp_Explorer.hxx>
75 #include <TopoDS.hxx>
76 #include <TopoDS_Edge.hxx>
77 #include <TopoDS_Face.hxx>
78 #include <TopoDS_Shape.hxx>
79 #include <TopoDS_Vertex.hxx>
80 #include <TopoDS_Wire.hxx>
81 #include <TopTools_IndexedMapOfShape.hxx>
82 #include <TopTools_ListIteratorOfListOfShape.hxx>
83 #include <TopTools_MapOfShape.hxx>
84 #include <TopTools_SequenceOfShape.hxx>
85
86 #ifdef OCCT_DEBUG
87 static Standard_Boolean Affich = Standard_False;
88 static Standard_Integer NbOFFSET = 0;
89 #endif
90 #ifdef DRAW 
91 #include <DrawTrSurf.hxx>
92 #include <DBRep.hxx>
93 #endif
94 #include <stdio.h>
95 #include <Geom_BSplineSurface.hxx>
96
97
98 static gp_Pnt GetFarestCorner(const TopoDS_Wire& aWire)
99 {
100   TopTools_IndexedMapOfShape Vertices;
101   TopExp::MapShapes(aWire, TopAbs_VERTEX, Vertices);
102
103   Standard_Real MaxDist = 0.;
104   gp_Pnt thePoint;
105   for (Standard_Integer i = 1; i <= Vertices.Extent(); i++)
106     for (Standard_Integer j = 1; j <= Vertices.Extent(); j++)
107     {
108       const TopoDS_Vertex& V1 = TopoDS::Vertex(Vertices(i));
109       const TopoDS_Vertex& V2 = TopoDS::Vertex(Vertices(j));
110       gp_Pnt P1 = BRep_Tool::Pnt(V1);
111       gp_Pnt P2 = BRep_Tool::Pnt(V2);
112       Standard_Real aDist = P1.SquareDistance(P2);
113       if (aDist > MaxDist)
114       {
115         MaxDist = aDist;
116         thePoint = P1;
117       }
118     }
119
120   return thePoint;
121 }
122
123 //=======================================================================
124 //function : UpdateEdge
125 //purpose  : 
126 //=======================================================================
127
128 static void UpdateEdge(const TopoDS_Edge& E, 
129                        const Handle(Geom_Curve)& C, 
130                        const TopLoc_Location& L,
131                        const Standard_Real Tol)
132 {
133   // Cut curves to avoid copies in the extensions. 
134   BRep_Builder B;
135   Handle(Geom_TrimmedCurve) BC = Handle(Geom_TrimmedCurve)::DownCast(C);
136   if (!BC.IsNull()) {
137     B.UpdateEdge(E,BC->BasisCurve(),L,Tol);
138   }
139   else {
140     B.UpdateEdge(E,C,L,Tol);
141   }
142 }
143
144 //=======================================================================
145 //function : UpdateEdge
146 //purpose  : 
147 //=======================================================================
148
149 static void UpdateEdge(const TopoDS_Edge& E, 
150                        const Handle(Geom2d_Curve)& C, 
151                        const TopoDS_Face& F, 
152                        const Standard_Real Tol) 
153 {
154   // Cut curves to avoid copies in the extensions. 
155   BRep_Builder B;
156   Handle(Geom2d_TrimmedCurve) BC = Handle(Geom2d_TrimmedCurve)::DownCast(C);
157   if (!BC.IsNull()) {
158     B.UpdateEdge(E,BC->BasisCurve(),F,Tol);
159   }
160   else {
161     B.UpdateEdge(E,C,F,Tol);
162   }
163 }
164
165 //=======================================================================
166 //function : UpdateEdge
167 //purpose  : 
168 //=======================================================================
169
170 static void UpdateEdge (const TopoDS_Edge& E, 
171                         const Handle(Geom2d_Curve)& C1, 
172                         const Handle(Geom2d_Curve)& C2, 
173                         const TopoDS_Face& F, 
174                         const Standard_Real Tol) 
175 {
176   // Cut curves to avoid copies in the extensions. 
177   BRep_Builder B;
178   Handle(Geom2d_Curve) NC1,NC2;
179   Handle(Geom2d_TrimmedCurve) BC1 = Handle(Geom2d_TrimmedCurve)::DownCast(C1);
180   Handle(Geom2d_TrimmedCurve) BC2 = Handle(Geom2d_TrimmedCurve)::DownCast(C2);
181   if (!BC1.IsNull()) NC1 = BC1->BasisCurve(); else NC1 = C1;
182   if (!BC2.IsNull()) NC2 = BC2->BasisCurve(); else NC2 = C2;
183   B.UpdateEdge(E,NC1,NC2,F,Tol);
184 }
185
186
187 //=======================================================================
188 //function : ComputeCurve3d
189 //purpose  : Particular case of Curve On Surface. 
190 //=======================================================================
191
192 static void ComputeCurve3d(TopoDS_Edge           Edge,
193                            const Handle(Geom2d_Curve)& Curve,
194                            const Handle(Geom_Surface)& Surf,
195                            const TopLoc_Location Loc,
196                            Standard_Real         Tol)
197 {
198   // try to find the particular case
199   // if not found call BRepLib::BuildCurve3d
200
201   Standard_Boolean IsComputed = Standard_False;
202
203   // Search only isos on analytic surfaces.
204   Geom2dAdaptor_Curve C(Curve);
205   GeomAdaptor_Surface S(Surf);
206   GeomAbs_CurveType   CTy = C.GetType();
207   GeomAbs_SurfaceType STy = S.GetType();
208   BRep_Builder TheBuilder;
209
210   if ( STy != GeomAbs_Plane) { // if plane buildcurve3d manage KPart
211     if ( CTy == GeomAbs_Line) {
212       gp_Dir2d D = C.Line().Direction();
213       if ( D.IsParallel(gp::DX2d(),Precision::Angular())) { // Iso V.
214         if ( STy == GeomAbs_Sphere) {
215           gp_Pnt2d  P    = C.Line().Location();
216           if ( Abs( Abs(P.Y()) -M_PI/2. ) < Precision::PConfusion()) {
217             TheBuilder.Degenerated(Edge, Standard_True);
218           }
219           else {
220             gp_Sphere Sph  = S.Sphere();
221             gp_Ax3    Axis = Sph.Position();
222             gp_Circ   Ci   = ElSLib::SphereVIso(Axis,
223                                                 Sph.Radius(),
224                                                 P.Y());
225             gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
226             gp_Ax1 AxeRev(Axis.Location(), DRev);
227             Ci.Rotate(AxeRev, P.X());
228             Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
229             if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
230               Circle->Reverse();
231             UpdateEdge(Edge, Circle, Loc, Tol);
232           }
233           IsComputed = Standard_True;
234         }
235         else if ( STy == GeomAbs_Cylinder) {
236           gp_Cylinder Cyl  = S.Cylinder();
237           gp_Pnt2d    P    = C.Line().Location();
238           gp_Ax3      Axis = Cyl.Position();
239           gp_Circ     Ci   = ElSLib::CylinderVIso(Axis,
240                                                   Cyl.Radius(),
241                                                   P.Y());
242           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
243           gp_Ax1 AxeRev(Axis.Location(), DRev);
244           Ci.Rotate(AxeRev, P.X());
245           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
246           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
247             Circle->Reverse();
248           UpdateEdge(Edge, Circle, Loc, Tol);
249           IsComputed = Standard_True;
250         }
251         else if ( STy == GeomAbs_Cone) {
252           gp_Cone  Cone = S.Cone();
253           gp_Pnt2d P    = C.Line().Location();
254           gp_Ax3   Axis = Cone.Position();
255           gp_Circ  Ci   = ElSLib::ConeVIso(Axis,
256                                            Cone.RefRadius(),
257                                            Cone.SemiAngle(),
258                                            P.Y());
259           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
260           gp_Ax1 AxeRev(Axis.Location(), DRev);
261           Ci.Rotate(AxeRev, P.X());
262           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
263           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
264             Circle->Reverse();
265           UpdateEdge(Edge, Circle, Loc, Tol);
266           IsComputed = Standard_True;
267         }
268         else if ( STy == GeomAbs_Torus) {
269           gp_Torus Tore = S.Torus();
270           gp_Pnt2d P    = C.Line().Location();
271           gp_Ax3   Axis = Tore.Position();
272           gp_Circ  Ci   = ElSLib::TorusVIso(Axis,
273                                             Tore.MajorRadius(),
274                                             Tore.MinorRadius(),
275                                             P.Y());
276           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
277           gp_Ax1 AxeRev(Axis.Location(), DRev);
278           Ci.Rotate(AxeRev, P.X());
279           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
280           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) 
281             Circle->Reverse();
282           UpdateEdge(Edge, Circle, Loc, Tol);
283           IsComputed = Standard_True;
284         }
285       }
286       else if ( D.IsParallel(gp::DY2d(),Precision::Angular())) { // Iso U.
287         if ( STy == GeomAbs_Sphere) {
288           gp_Sphere Sph  = S.Sphere();
289           gp_Pnt2d  P    = C.Line().Location();
290           gp_Ax3    Axis = Sph.Position();
291           // calculate iso 0.
292           gp_Circ   Ci   = ElSLib::SphereUIso(Axis, Sph.Radius(),0.);
293
294           // set to sameparameter (rotation of circle - offset of Y)
295           gp_Dir DRev = Axis.XDirection().Crossed(Axis. Direction());
296           gp_Ax1 AxeRev(Axis.Location(),DRev);
297           Ci.Rotate(AxeRev, P.Y());
298
299           // transformation en iso U ( = P.X())
300           DRev = Axis.XDirection().Crossed(Axis.YDirection());
301           AxeRev = gp_Ax1(Axis.Location(), DRev);
302           Ci.Rotate(AxeRev, P.X());
303           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
304           
305           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) 
306             Circle->Reverse();
307           UpdateEdge(Edge, Circle, Loc, Tol);
308           IsComputed = Standard_True;
309         }
310         else if ( STy == GeomAbs_Cylinder) {
311           gp_Cylinder Cyl = S.Cylinder();
312           gp_Pnt2d    P   = C.Line().Location();
313           gp_Lin      L   = ElSLib::CylinderUIso(Cyl.Position(),
314                                                  Cyl.Radius(),
315                                                  P.X());
316           gp_Vec Tr(L.Direction());
317           Tr.Multiply(P.Y());
318           L.Translate(Tr);
319           Handle(Geom_Line) Line = new Geom_Line(L);
320           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
321             Line->Reverse();
322           UpdateEdge(Edge, Line, Loc, Tol);
323           IsComputed = Standard_True;
324         }
325         else if ( STy == GeomAbs_Cone) {
326           gp_Cone  Cone = S.Cone();
327           gp_Pnt2d P    = C.Line().Location();
328           gp_Lin   L    = ElSLib::ConeUIso(Cone.Position(),
329                                            Cone.RefRadius(),
330                                            Cone.SemiAngle(),
331                                            P.X());
332           gp_Vec Tr(L.Direction());
333           Tr.Multiply(P.Y());
334           L.Translate(Tr);        Handle(Geom_Line) Line = new Geom_Line(L);
335           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
336             Line->Reverse();
337           UpdateEdge(Edge, Line, Loc, Tol);
338           IsComputed = Standard_True;
339         }
340         else if ( STy == GeomAbs_Torus) {
341           gp_Torus Tore = S.Torus();
342           gp_Pnt2d P    = C.Line().Location();
343           gp_Ax3   Axis = Tore.Position();
344           gp_Circ  Ci   = ElSLib::TorusUIso(Axis,
345                                             Tore.MajorRadius(),
346                                             Tore.MinorRadius(),
347                                             P.X());
348           Ci.Rotate(Ci.Axis(),P.Y());
349           Handle(Geom_Circle) Circle = new Geom_Circle(Ci);
350           
351           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) 
352             Circle->Reverse();
353           UpdateEdge(Edge, Circle, Loc, Tol);
354           IsComputed = Standard_True;
355         }
356       }
357     }
358   }
359   else { // Cas Plan
360     Handle(Geom_Curve) C3d = GeomAPI::To3d(Curve,S.Plane());
361     UpdateEdge(Edge, C3d, Loc, Tol);
362     IsComputed = Standard_True;
363   }
364   if ( !IsComputed) {
365     //BRepLib::BuildCurves3d(Edge,Tol);
366     //Les Courbes 3d des edges dans le cas general ne sont calcules que si 
367     // necessaire
368     //ie dans les tuyaux et les bouchons ..
369     // dans la derniere etapes de MakeShells on reconstruira les courbes3d
370     // des edges du resultat qui n en ont pas.
371   }
372 }
373
374
375 //=======================================================================
376 //function : BRepOffset_Offset
377 //purpose  : 
378 //=======================================================================
379
380 BRepOffset_Offset::BRepOffset_Offset()
381 {
382 }
383
384
385 //=======================================================================
386 //function : BRepOffset_Offset
387 //purpose  : 
388 //=======================================================================
389
390 BRepOffset_Offset::BRepOffset_Offset(const TopoDS_Face&  Face, 
391                                      const Standard_Real Offset,
392                                      const Standard_Boolean OffsetOutside,
393                                      const GeomAbs_JoinType JoinType)
394 {
395   Init(Face, Offset, OffsetOutside, JoinType);
396 }
397
398
399 //=======================================================================
400 //function : BRepOffset_Offset
401 //purpose  : 
402 //=======================================================================
403
404 BRepOffset_Offset::BRepOffset_Offset
405 (const TopoDS_Face&                  Face,
406  const Standard_Real                 Offset,
407  const TopTools_DataMapOfShapeShape& Created,
408  const Standard_Boolean              OffsetOutside,
409  const GeomAbs_JoinType              JoinType)
410 {
411   Init(Face,Offset,Created,OffsetOutside,JoinType);
412 }
413
414
415 //=======================================================================
416 //function : BRepOffset_Offset
417 //purpose  : 
418 //=======================================================================
419
420 BRepOffset_Offset::BRepOffset_Offset(const TopoDS_Edge&     Path,
421                                      const TopoDS_Edge&     Edge1,
422                                      const TopoDS_Edge&     Edge2,
423                                      const Standard_Real    Offset,
424                                      const Standard_Boolean Polynomial,
425                                      const Standard_Real    Tol,
426                                      const GeomAbs_Shape    Conti)
427 {
428   Init(Path,Edge1,Edge2,Offset,Polynomial,Tol,Conti);
429 }
430
431
432 //=======================================================================
433 //function : BRepOffset_Offset
434 //purpose  : 
435 //=======================================================================
436
437 BRepOffset_Offset::BRepOffset_Offset
438 (const TopoDS_Edge&     Path,
439  const TopoDS_Edge&     Edge1,
440  const TopoDS_Edge&     Edge2,
441  const Standard_Real    Offset,
442  const TopoDS_Edge&     FirstEdge,
443  const TopoDS_Edge&     LastEdge,
444  const Standard_Boolean Polynomial,
445  const Standard_Real    Tol,
446  const GeomAbs_Shape    Conti)
447 {
448   Init(Path,Edge1,Edge2,Offset,FirstEdge,LastEdge,Polynomial,Tol,Conti);
449 }
450
451
452 //=======================================================================
453 //function : BRepOffset_Offset
454 //purpose  : 
455 //=======================================================================
456
457 BRepOffset_Offset::BRepOffset_Offset(const TopoDS_Vertex&        Vertex,
458                                      const TopTools_ListOfShape& LEdge,
459                                      const Standard_Real         Offset,
460                                      const Standard_Boolean      Polynomial,
461                                      const Standard_Real         Tol,
462                                      const GeomAbs_Shape         Conti)
463 {
464   Init(Vertex,LEdge,Offset,Polynomial,Tol,Conti);
465 }
466
467
468 //=======================================================================
469 //function : Init
470 //purpose  : 
471 //=======================================================================
472
473 void BRepOffset_Offset::Init(const TopoDS_Face&  Face,
474                              const Standard_Real Offset,
475                              const Standard_Boolean OffsetOutside,
476                              const GeomAbs_JoinType JoinType)
477 {
478   TopTools_DataMapOfShapeShape Empty;
479   Init(Face,Offset,Empty,OffsetOutside,JoinType);
480 }
481
482
483 //=======================================================================
484 //function : Init
485 //purpose  : 
486 //=======================================================================
487
488 void BRepOffset_Offset::Init(const TopoDS_Face&                  Face,
489                              const Standard_Real                 Offset,
490                              const TopTools_DataMapOfShapeShape& Created,
491                              const Standard_Boolean              OffsetOutside,
492                              const GeomAbs_JoinType              JoinType)
493 {
494   myShape   = Face;
495   Standard_Real myOffset = Offset;
496   if ( Face.Orientation() == TopAbs_REVERSED) 
497     myOffset *= -1.;
498
499   TopLoc_Location L;
500   Handle(Geom_Surface) S = BRep_Tool::Surface(Face,L);
501   // On detrime les surfaces, evite des recopies dans les extensions.
502   Handle(Geom_RectangularTrimmedSurface) RT = 
503     Handle(Geom_RectangularTrimmedSurface)::DownCast(S);
504   if (!RT.IsNull()) S = RT->BasisSurface();
505   Standard_Boolean IsTransformed = Standard_False;
506   if ((S->IsKind(STANDARD_TYPE(Geom_BSplineSurface)) || 
507       S->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) ||
508       S->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)) ||
509       S->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) && !L.IsIdentity())
510   {
511     S = Handle(Geom_Surface)::DownCast(S->Copy());
512     S->Transform(L.Transformation());
513     IsTransformed = Standard_True;
514   }
515   // particular case of cone
516   Handle(Geom_ConicalSurface) Co;
517   Co = Handle(Geom_ConicalSurface)::DownCast(S);
518   if ( !Co.IsNull()) {
519     Standard_Real Uc,Vc;
520     gp_Pnt Apex = Co->Apex();
521     ElSLib::Parameters( Co->Cone(),Apex,Uc,Vc);
522     Standard_Real UU1,UU2,VV1,VV2;
523     BRepTools::UVBounds(Face,UU1,UU2,VV1,VV2);
524     if ( VV2 < Vc && Co->SemiAngle() > 0 ) 
525       myOffset *= -1;
526     else if ( VV1 > Vc && Co->SemiAngle() < 0 ) 
527       myOffset *= -1;
528     if ( !Co->Position().Direct()) myOffset *= -1;
529   }
530
531   Handle(Geom_Surface) TheSurf = 
532     BRepOffset::Surface( S, myOffset, myStatus);
533
534   //processing offsets of faces with possible degenerated edges
535   Standard_Boolean UminDegen = Standard_False;
536   Standard_Boolean UmaxDegen = Standard_False;
537   Standard_Boolean VminDegen = Standard_False;
538   Standard_Boolean VmaxDegen = Standard_False;
539   Standard_Boolean UisoDegen = Standard_False;
540   gp_Pnt MinApex, MaxApex;
541   Standard_Boolean HasSingularity = Standard_False;
542   Standard_Real uf1, uf2, vf1, vf2, fpar, lpar;
543   BRepTools::UVBounds(Face, uf1, uf2, vf1, vf2);
544   if (!(OffsetOutside && JoinType == GeomAbs_Arc) &&
545       (TheSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface) ||
546        TheSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)))
547     {
548       TopTools_SequenceOfShape DegEdges;
549       TopExp_Explorer Explo(Face, TopAbs_EDGE);
550       for (; Explo.More(); Explo.Next())
551       {
552         const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
553
554         if (BRep_Tool::Degenerated(anEdge))
555         {
556           Standard_Real aF, aL;
557           Handle(Geom2d_Curve) c2d =  BRep_Tool::CurveOnSurface(anEdge, Face, aF, aL);
558
559           gp_Pnt2d aFPnt2d = c2d->Value(aF),
560                    aLPnt2d = c2d->Value(aL);
561
562           gp_Pnt aFPnt = S->Value(aFPnt2d.X(), aFPnt2d.Y()),
563                  aLPnt = S->Value(aLPnt2d.X(), aLPnt2d.Y());
564
565           //  aFPnt.SquareDistance(aLPnt) > Precision::SquareConfusion() -
566           // is a sufficient condition of troubles: non-singular case, but edge is degenerated.
567           // So, normal handling of degenerated edges is not applicable in case of non-singular point.
568           if (aFPnt.SquareDistance(aLPnt) < Precision::SquareConfusion())
569           {
570             DegEdges.Append(anEdge);
571           }
572         }
573       }
574       if (!DegEdges.IsEmpty())
575         {
576           const Standard_Real TolApex = 1.e-5;
577           //define the iso of singularity (u or v)
578           TopoDS_Edge theDegEdge = TopoDS::Edge(DegEdges(1));
579           Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(theDegEdge, Face, fpar, lpar);
580           gp_Pnt2d fp2d = aCurve->Value(fpar);
581           gp_Pnt2d lp2d = aCurve->Value(lpar);
582           if (Abs(fp2d.X() - lp2d.X()) <= Precision::PConfusion())
583             UisoDegen = Standard_True;
584
585           if (DegEdges.Length() == 2)
586             {
587               if (UisoDegen)
588               { UminDegen = Standard_True; UmaxDegen = Standard_True; }
589               else
590               { VminDegen = Standard_True; VmaxDegen = Standard_True; }
591             }
592           else //DegEdges.Length() == 1
593             {
594               if (UisoDegen)
595               {
596                 if (Abs(fp2d.X() - uf1) <= Precision::Confusion())
597                   UminDegen = Standard_True;
598                 else
599                   UmaxDegen = Standard_True;
600               }
601               else
602               {
603                 if (Abs(fp2d.Y() - vf1) <= Precision::Confusion())
604                   VminDegen = Standard_True;
605                 else
606                   VmaxDegen = Standard_True;
607               }
608             }
609           if (TheSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
610             {
611               gp_Cone theCone = Handle(Geom_ConicalSurface)::DownCast (TheSurf)->Cone();
612               gp_Pnt apex = theCone.Apex();
613               Standard_Real Uapex, Vapex;
614               ElSLib::Parameters( theCone, apex, Uapex, Vapex );
615               if (VminDegen)
616                 {
617                   TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, Vapex, vf2);
618                   MinApex = apex;
619                   HasSingularity = Standard_True;
620                 }
621               else if (VmaxDegen)
622                 {
623                   TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, Vapex);
624                   MaxApex = apex;
625                   HasSingularity = Standard_True;
626                 }
627             }
628           else //TheSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)
629             {
630               if (UminDegen)
631               {
632                 Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
633                 if (BRepOffset_Tool::Gabarit( uiso ) > TolApex)
634                 {
635                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
636                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
637                   Papex = BasisSurf->Value( uf1, vf1 );
638                   Pfirst = TheSurf->Value( uf1, vf1 );
639                   Pquart = TheSurf->Value( uf1, 0.75*vf1+0.25*vf2 );
640                   Pmid   = TheSurf->Value( uf1, 0.5*(vf1+vf2) );
641                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
642                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
643                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf1, 1, 0 );
644                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
645                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
646                   gp_Pnt Pint1, Pint2;
647                   theExtrema.NearestPoints(Pint1, Pint2);
648                   Standard_Real length = Pfirst.Distance(Pint1);
649                   if (OffsetOutside)
650                   {
651                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
652                     GeomLib::ExtendSurfByLength (aSurf, length, 1, Standard_True, Standard_False);
653                     TheSurf = aSurf;
654                     Standard_Real u1, u2, v1, v2;
655                     TheSurf->Bounds( u1, u2, v1, v2 );
656                     MinApex = TheSurf->Value( u1, vf1 );
657                   }
658                   else
659                   {
660                     Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
661                     GeomAPI_ProjectPointOnCurve Projector( Pint1, viso );
662                     Standard_Real NewFirstU = Projector.LowerDistanceParameter();
663                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, NewFirstU, uf2, vf1, vf2);
664                     MinApex = TheSurf->Value( NewFirstU, vf1 );
665                   }
666                   HasSingularity = Standard_True;
667                 }
668               } //end of if (UminDegen)
669               if (UmaxDegen)
670               {
671                 Handle(Geom_Curve) uiso = TheSurf->UIso( uf2 );
672                 if (BRepOffset_Tool::Gabarit( uiso ) > TolApex)
673                 {
674                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
675                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
676                   Papex  = BasisSurf->Value( uf2, vf1 );
677                   Pfirst = TheSurf->Value( uf2, vf1 );
678                   Pquart = TheSurf->Value( uf2, 0.75*vf1+0.25*vf2 );
679                   Pmid   = TheSurf->Value( uf2, 0.5*(vf1+vf2) );
680                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
681                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
682                   gp_Vec DirGeneratrix = BasisSurf->DN( uf2, vf1, 1, 0 );
683                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
684                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
685                   gp_Pnt Pint1, Pint2;
686                   theExtrema.NearestPoints(Pint1, Pint2);
687                   Standard_Real length = Pfirst.Distance(Pint1);
688                   if (OffsetOutside)
689                   {
690                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
691                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_True, Standard_True);
692                     TheSurf = aSurf;
693                     Standard_Real u1, u2, v1, v2;
694                     TheSurf->Bounds( u1, u2, v1, v2 );
695                     MaxApex = TheSurf->Value( u2, vf1 );
696                   }
697                   else
698                   {
699                     Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
700                     GeomAPI_ProjectPointOnCurve Projector( Pint1, viso );
701                     Standard_Real NewLastU = Projector.LowerDistanceParameter();
702                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, NewLastU, vf1, vf2);
703                     MaxApex = TheSurf->Value( NewLastU, vf1 );
704                   }
705                   HasSingularity = Standard_True;
706                 }
707               } //end of if (UmaxDegen)
708               if (VminDegen)
709               {
710                 Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
711                 if (BRepOffset_Tool::Gabarit( viso ) > TolApex)
712                 {
713                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
714                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
715                   Papex = BasisSurf->Value( uf1, vf1 );
716                   Pfirst = TheSurf->Value( uf1, vf1 );
717                   Pquart = TheSurf->Value( 0.75*uf1+0.25*uf2, vf1 );
718                   Pmid   = TheSurf->Value( 0.5*(uf1+uf2), vf1 );
719                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
720                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
721                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf1, 0, 1 );
722                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
723                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
724                   gp_Pnt Pint1, Pint2;
725                   theExtrema.NearestPoints(Pint1, Pint2);
726                   Standard_Real length = Pfirst.Distance(Pint1);
727                   if (OffsetOutside)
728                   {
729                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
730                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_False, Standard_False);
731                     TheSurf = aSurf;
732                     Standard_Real u1, u2, v1, v2;
733                     TheSurf->Bounds( u1, u2, v1, v2 );
734                     MinApex = TheSurf->Value( uf1, v1 );
735                   }
736                   else
737                   {
738                     Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
739                     GeomAPI_ProjectPointOnCurve Projector( Pint1, uiso );
740                     Standard_Real NewFirstV = Projector.LowerDistanceParameter();
741                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, NewFirstV, vf2);
742                     MinApex = TheSurf->Value( uf1, NewFirstV );
743                     //TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1+length, vf2);
744                     //MinApex = TheSurf->Value( uf1, vf1+length );
745                   }
746                   HasSingularity = Standard_True;
747                 }
748               } //end of if (VminDegen)
749               if (VmaxDegen)
750               {
751                 Handle(Geom_Curve) viso = TheSurf->VIso( vf2 );
752                 if (BRepOffset_Tool::Gabarit( viso ) > TolApex)
753                 {
754                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
755                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
756                   Papex = BasisSurf->Value( uf1, vf2 );
757                   Pfirst = TheSurf->Value( uf1, vf2 );
758                   Pquart = TheSurf->Value( 0.75*uf1+0.25*uf2, vf2 );
759                   Pmid   = TheSurf->Value( 0.5*(uf1+uf2), vf2 );
760                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
761                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
762                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf2, 0, 1 );
763                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
764                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
765                   gp_Pnt Pint1, Pint2;
766                   theExtrema.NearestPoints(Pint1, Pint2);
767                   Standard_Real length = Pfirst.Distance(Pint1);
768                   if (OffsetOutside)
769                   {
770                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
771                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_False, Standard_True);
772                     TheSurf = aSurf;
773                     Standard_Real u1, u2, v1, v2;
774                     TheSurf->Bounds( u1, u2, v1, v2 );
775                     MaxApex = TheSurf->Value( uf1, v2 );
776                   }
777                   else
778                   {
779                     Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
780                     GeomAPI_ProjectPointOnCurve Projector( Pint1, uiso );
781                     Standard_Real NewLastV = Projector.LowerDistanceParameter();
782                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, NewLastV);
783                     MaxApex = TheSurf->Value( uf1, NewLastV );
784                     //TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2-length);
785                     //MaxApex = TheSurf->Value( uf1, vf2-length );
786                   }
787                   HasSingularity = Standard_True;
788                 }
789               } //end of if (VmaxDegen)
790             } //end of else (case of Geom_OffsetSurface)
791         } //end of if (!DegEdges.IsEmpty())
792     } //end of processing offsets of faces with possible degenerated edges
793   
794   // find the PCurves of the edges of <Faces> 
795
796   BRep_Builder myBuilder;
797   myBuilder.MakeFace(myFace);
798   if  (!IsTransformed)
799     myBuilder.UpdateFace(myFace,TheSurf, L, BRep_Tool::Tolerance(Face));
800   else
801     myBuilder.UpdateFace(myFace,TheSurf, TopLoc_Location(), BRep_Tool::Tolerance(Face));
802
803   TopTools_DataMapOfShapeShape MapSS;
804
805   // mise a jour de la map sur les vertex deja crees
806   TopoDS_Shape aLocalShapeOriented = Face.Oriented(TopAbs_FORWARD);
807   TopoDS_Face CurFace = TopoDS::Face(aLocalShapeOriented);
808 //  TopoDS_Face CurFace = TopoDS::Face(Face.Oriented(TopAbs_FORWARD));
809
810   TopTools_MapOfShape VonDegen;
811   Standard_Real u1, u2, v1, v2;
812   TheSurf->Bounds( u1, u2, v1, v2 );
813
814   TopExp_Explorer exp(CurFace, TopAbs_EDGE);
815   for ( ; exp.More(); exp.Next()) {
816     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
817     TopoDS_Vertex V1,V2,OV1,OV2;
818     TopExp::Vertices(E ,V1 ,V2 );
819     if (HasSingularity && BRep_Tool::Degenerated(E))
820       VonDegen.Add( V1 );
821     if (Created.IsBound(E)) {
822       const TopoDS_Edge& OE = TopoDS::Edge(Created(E));
823       TopExp::Vertices(OE,OV1,OV2);
824       if (!MapSS.IsBound(V1)) MapSS.Bind(V1,OV1);
825       if (!MapSS.IsBound(V2)) MapSS.Bind(V2,OV2);
826     }
827     if (Created.IsBound(V1)) {
828       if (!MapSS.IsBound(V1)) MapSS.Bind(V1,Created(V1));
829     }
830     if (Created.IsBound(V2)) {
831       if (!MapSS.IsBound(V2)) MapSS.Bind(V2,Created(V2));
832     }
833   }
834
835   TopExp_Explorer expw(CurFace, TopAbs_WIRE);
836   for ( ; expw.More(); expw.Next()) {
837     const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
838     TopExp_Explorer expe(W.Oriented(TopAbs_FORWARD),
839                          TopAbs_EDGE);
840     TopoDS_Wire OW;
841     myBuilder.MakeWire(OW);
842     for ( ; expe.More(); expe.Next()) {
843       const TopoDS_Edge& E = TopoDS::Edge(expe.Current());
844       TopoDS_Vertex V1,V2;
845       TopExp::Vertices(E,V1,V2);
846       gp_Pnt2d P2d1, P2d2;
847       gp_Pnt P1, P2;
848       Standard_Real vstart, vend;
849       Standard_Real f,l;
850       Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E,CurFace,f,l);
851       TopoDS_Edge OE;
852       if (MapSS.IsBound(E) &&
853           !VonDegen.Contains(V1) && !VonDegen.Contains(V2)) { // c`est un edge de couture 
854         OE = TopoDS::Edge(MapSS(E));
855         TopoDS_Shape aLocalShape = E.Reversed();
856         Handle(Geom2d_Curve) C2d_1 = 
857           BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShape),CurFace,f,l);
858 //      Handle(Geom2d_Curve) C2d_1 = 
859 //        BRep_Tool::CurveOnSurface(TopoDS::Edge(E.Reversed()),CurFace,f,l);
860         if ( E.Orientation() == TopAbs_FORWARD)
861           UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
862         else
863           UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
864         myBuilder.Range(OE,f,l);
865       }
866       else {
867         TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
868         TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
869         P2d1 = C2d->Value(BRep_Tool::Parameter(V1,Eforward,CurFace));
870         P2d2 = C2d->Value(BRep_Tool::Parameter(V2,Eforward,CurFace));
871         if (VonDegen.Contains(V1))
872           {
873             if (Abs(P2d1.Y() - vf1) <= Precision::Confusion())
874               {
875                 P1 = MinApex; vstart = v1;
876               }
877             else
878               {
879                 P1 = MaxApex; vstart = v2;
880               }
881           }
882         else
883           {
884             TheSurf->D0(P2d1.X(),P2d1.Y(),P1);
885             if (!L.IsIdentity() && !IsTransformed)
886               P1.Transform(L.Transformation());
887             vstart = P2d1.Y();
888           }
889         if (VonDegen.Contains(V2))
890           {
891             if (Abs(P2d2.Y() - vf1) <= Precision::Confusion())
892               {
893                 P2 = MinApex; vend = v1;
894               }
895             else
896               {
897                 P2 = MaxApex; vend = v2;
898               }
899           }
900         else
901           {
902             TheSurf->D0(P2d2.X(),P2d2.Y(),P2);
903             if (!L.IsIdentity() && !IsTransformed)
904               P2.Transform(L.Transformation());
905             vend = P2d2.Y();
906           }
907         // E a-t-il ume image dans la Map des Created ?
908         if ( Created.IsBound(E)) {
909           OE = TopoDS::Edge(Created(E));
910         }
911         else if (MapSS.IsBound(E)) //seam edge
912           OE = TopoDS::Edge(MapSS(E));
913         else {
914           myBuilder.MakeEdge(OE);
915           TopoDS_Vertex OV1,OV2;
916           if ( MapSS.IsBound(V1)) {
917             OV1 = TopoDS::Vertex(MapSS(V1));
918           }
919           else {
920             myBuilder.MakeVertex(OV1);
921             myBuilder.UpdateVertex(OV1,P1,BRep_Tool::Tolerance(V1));
922             MapSS.Bind(V1,OV1);
923           }
924           if ( MapSS.IsBound(V2)) {
925             OV2 = TopoDS::Vertex(MapSS(V2));
926           }
927           else {
928             myBuilder.MakeVertex(OV2);
929             myBuilder.UpdateVertex(OV2,P2,BRep_Tool::Tolerance(V2));
930             MapSS.Bind(V2,OV2);
931           }
932           myBuilder.Add(OE,OV1.Oriented(V1.Orientation()));
933           myBuilder.Add(OE,OV2.Oriented(V2.Orientation()));
934           if (BRep_Tool::Degenerated(E)) {
935             myBuilder.Degenerated(OE, Standard_True);
936             /*
937 #ifdef OCCT_DEBUG
938             gp_Pnt        P1,P2;
939             gp_Pnt2d      P2d;
940             P2d = C2d->Value(f); TheSurf->D0(P2d.X(),P2d.Y(),P1);
941             P2d = C2d->Value(l); TheSurf->D0(P2d.X(),P2d.Y(),P2);         
942             Standard_Real Tol = BRep_Tool::Tolerance(V1); 
943             if (!P1.IsEqual(P2,Tol)) {
944               std::cout <<"BRepOffset_Offset : E degenerated -> OE not degenerated"<<std::endl; 
945             }
946 #endif    
947             */
948           }
949         }
950         if (VonDegen.Contains(V1) || VonDegen.Contains(V2))
951           {
952             if (VonDegen.Contains(V1))
953               P2d1.SetY( vstart );
954             if (VonDegen.Contains(V2))
955               P2d2.SetY( vend );
956             C2d = new Geom2d_Line( P2d1, gp_Vec2d(P2d1, P2d2) );
957             f = 0.; l = P2d1.Distance( P2d2 );
958             if (MapSS.IsBound(E)) //seam edge
959               {
960                 Handle(Geom2d_Curve) C2d_1 = BRep_Tool::CurveOnSurface(OE, myFace, f, l);
961                 if (E.Orientation() == TopAbs_FORWARD)
962                   UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
963                 else
964                   UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
965               }
966             else
967               UpdateEdge(OE,C2d,myFace,BRep_Tool::Tolerance(E));
968             //myBuilder.Range(OE,f,l);
969             myBuilder.Range(OE, myFace, f, l);
970             if (!BRep_Tool::Degenerated(E) && TheSurf->IsUClosed())
971               {
972                 TopoDS_Shape aLocalShapeReversedE = E.Reversed();
973                 Handle(Geom2d_Curve) C2d_1 = 
974                   BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShapeReversedE),CurFace,f,l);
975                 P2d1 = C2d_1->Value(BRep_Tool::Parameter(V1,E,CurFace));
976                 P2d2 = C2d_1->Value(BRep_Tool::Parameter(V2,E,CurFace));
977                 if (VonDegen.Contains(V1))
978                   P2d1.SetY( vstart );
979                 if (VonDegen.Contains(V2))
980                   P2d2.SetY( vend );
981                 C2d_1 = new Geom2d_Line( P2d1, gp_Vec2d(P2d1, P2d2) );
982                 if ( E.Orientation() == TopAbs_FORWARD)
983                   UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
984                 else
985                   UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
986               }
987             /*
988             if (!BRep_Tool::Degenerated(E))
989               {
990                 Handle(Geom_Line) theLine = new Geom_Line( P1, gp_Vec(P1, P2) );
991                 myBuilder.UpdateEdge( OE, theLine, BRep_Tool::Tolerance(E) );
992               }
993             */
994           }
995         else
996           {
997             UpdateEdge(OE,C2d,myFace,BRep_Tool::Tolerance(E));
998             myBuilder.Range(OE,f,l);
999             //ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
1000           }
1001         if (!BRep_Tool::Degenerated(OE))
1002           ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
1003         MapSS.Bind(E,OE);
1004       }
1005       myBuilder.Add(OW, OE.Oriented(E.Orientation()));
1006     }
1007     myBuilder.Add(myFace, OW.Oriented(W.Orientation()));
1008   }
1009
1010   myFace.Orientation(Face.Orientation());
1011   
1012   BRepTools::Update(myFace);
1013 }
1014
1015
1016 //=======================================================================
1017 //function : Init
1018 //purpose  : 
1019 //=======================================================================
1020
1021 void BRepOffset_Offset::Init(const TopoDS_Edge&     Path,
1022                              const TopoDS_Edge&     Edge1,
1023                              const TopoDS_Edge&     Edge2, 
1024                              const Standard_Real    Offset,
1025                              const Standard_Boolean Polynomial,
1026                              const Standard_Real    Tol,
1027                              const GeomAbs_Shape    Conti)
1028 {
1029   TopoDS_Edge FirstEdge,LastEdge;
1030   Init(Path,Edge1,Edge2,Offset,FirstEdge,LastEdge,Polynomial,Tol,Conti);
1031 }
1032
1033
1034 //=======================================================================
1035 //function : Init
1036 //purpose  : 
1037 //=======================================================================
1038
1039 void BRepOffset_Offset::Init(const TopoDS_Edge&     Path,
1040                              const TopoDS_Edge&     Edge1,
1041                              const TopoDS_Edge&     Edge2, 
1042                              const Standard_Real    Offset,
1043                              const TopoDS_Edge&     FirstEdge,
1044                              const TopoDS_Edge&     LastEdge,
1045                              const Standard_Boolean Polynomial,
1046                              const Standard_Real    Tol,
1047                              const GeomAbs_Shape    Conti)
1048 {
1049   Standard_Boolean C1Denerated = Standard_False;
1050   Standard_Boolean C2Denerated = Standard_False;
1051   myStatus = BRepOffset_Good;
1052   myShape = Path;
1053
1054   TopLoc_Location Loc;
1055   Standard_Real f[3],l[3];
1056
1057   Handle(Geom_Curve) CP = BRep_Tool::Curve(Path,Loc,f[0],l[0]);
1058   CP = new Geom_TrimmedCurve(CP,f[0], l[0]);
1059   CP->Transform(Loc.Transformation());
1060   Handle(GeomAdaptor_HCurve) HCP = new GeomAdaptor_HCurve(CP);
1061
1062   Handle(Geom_Curve) C1 = BRep_Tool::Curve(Edge1,Loc,f[1],l[1]);
1063
1064   Handle(Adaptor3d_HCurve) HEdge1;
1065   Standard_Boolean C1is3D = Standard_True;
1066   if (C1.IsNull()) {
1067     C1is3D = Standard_False;
1068     Handle(Geom2d_Curve) C12d;
1069     Handle(Geom_Surface) S1;
1070     BRep_Tool::CurveOnSurface(Edge1,C12d,S1,Loc,f[1],l[1]);
1071     S1 = Handle(Geom_Surface)::DownCast(S1->Transformed(Loc.Transformation()));
1072     C12d = new Geom2d_TrimmedCurve(C12d,f[1],l[1]);
1073     Handle(GeomAdaptor_HSurface) HS1 = new GeomAdaptor_HSurface(S1);
1074     Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C12d);
1075     Adaptor3d_CurveOnSurface Cons(HC1,HS1);
1076     HEdge1 = new Adaptor3d_HCurveOnSurface(Cons);
1077   }
1078   else {
1079     C1 = new Geom_TrimmedCurve(C1, f[1], l[1]);
1080     C1->Transform(Loc.Transformation());
1081     HEdge1 = new GeomAdaptor_HCurve(C1);
1082     GeomAdaptor_Curve AC1(C1);
1083     if ( AC1.GetType() == GeomAbs_Circle) {
1084       C1Denerated = (AC1.Circle().Radius() < Precision::Confusion());
1085     }
1086   }
1087
1088   Handle(Geom_Curve) C2 = BRep_Tool::Curve(Edge2,Loc,f[2],l[2]);
1089
1090   Handle(Adaptor3d_HCurve) HEdge2;
1091   Standard_Boolean C2is3D = Standard_True;
1092   if (C2.IsNull()) {
1093     C2is3D = Standard_False;
1094     Handle(Geom2d_Curve) C12d;
1095     Handle(Geom_Surface) S1;
1096     BRep_Tool::CurveOnSurface(Edge2,C12d,S1,Loc,f[2],l[2]);
1097     S1 = Handle(Geom_Surface)::DownCast(S1->Transformed(Loc.Transformation()));
1098     C12d = new Geom2d_TrimmedCurve(C12d,f[2],l[2]);
1099     Handle(GeomAdaptor_HSurface) HS1 = new GeomAdaptor_HSurface(S1);
1100     Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C12d);
1101     Adaptor3d_CurveOnSurface Cons(HC1,HS1);
1102     HEdge2 = new Adaptor3d_HCurveOnSurface(Cons);
1103   }
1104   else {
1105     C2 = new Geom_TrimmedCurve(C2, f[2], l[2]);
1106     C2->Transform(Loc.Transformation());
1107     HEdge2 = new GeomAdaptor_HCurve(C2);
1108     GeomAdaptor_Curve AC2(C2);
1109     if ( AC2.GetType() == GeomAbs_Circle) {
1110       C2Denerated = (AC2.Circle().Radius() < Precision::Confusion());
1111     }
1112   }
1113   
1114   // Calcul du tuyau
1115   GeomFill_Pipe Pipe(HCP, HEdge1, HEdge2, Abs(Offset));
1116   Pipe.Perform(Tol, Polynomial, Conti);
1117   if (!Pipe.IsDone())
1118     throw Standard_ConstructionError("GeomFill_Pipe : Cannot make a surface");
1119   Standard_Real ErrorPipe = Pipe.ErrorOnSurf();
1120
1121   Handle(Geom_Surface) S = Pipe.Surface();
1122   Standard_Boolean ExchUV = Pipe.ExchangeUV();
1123   Standard_Real f1,l1,f2,l2;
1124   S->Bounds(f1,l1,f2,l2);
1125
1126   // Perform the face
1127   Standard_Real PathTol = BRep_Tool::Tolerance(Path);
1128   Standard_Real TheTol;
1129   BRep_Builder myBuilder;
1130   myBuilder.MakeFace(myFace);
1131   TopLoc_Location Id;
1132   myBuilder.UpdateFace(myFace,S,Id,PathTol);
1133
1134   // update de Edge1. (Rem : has already a 3d curve)
1135   Standard_Real U,U1,U2;
1136   Handle(Geom2d_Curve) PC;
1137   if ( ExchUV) {
1138     PC = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1139     U1 = f1;
1140     U2 = l1;
1141     if (!C1is3D) C1 = S->VIso(f2);
1142   }
1143   else  {
1144     PC = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1145     U1 = f2;
1146     U2 = l2;
1147     if (!C1is3D) C1 = S->UIso(f1);
1148   }
1149   
1150   Handle(Geom_Curve) Dummy;
1151   if (!C1is3D)
1152     UpdateEdge(Edge1,C1,Id,BRep_Tool::Tolerance(Edge1));
1153   else if ( C1Denerated) {
1154     UpdateEdge(Edge1,Dummy,Id,BRep_Tool::Tolerance(Edge1));
1155     myBuilder.Degenerated(Edge1,Standard_True);
1156   }
1157
1158   TheTol = Max(PathTol, BRep_Tool::Tolerance(Edge1) + ErrorPipe);
1159   UpdateEdge(Edge1, PC, myFace, TheTol);
1160
1161   // mise a same range de la nouvelle pcurve.
1162   if ( !C1is3D && !C1Denerated)
1163   {
1164     myBuilder.SameRange    (Edge1,Standard_False);
1165     myBuilder.Range(Edge1,U1,U2, Standard_True);
1166   }
1167   myBuilder.Range(Edge1,myFace,U1,U2);
1168   BRepLib::SameRange(Edge1);
1169   
1170   // mise a sameparameter pour les KPart
1171   if (ErrorPipe == 0) {
1172     TheTol = Max(TheTol, Tol); 
1173     myBuilder.SameParameter(Edge1,Standard_False);
1174     BRepLib::SameParameter(Edge1, TheTol);
1175   }
1176   
1177   // Update de edge2. (Rem : has already a 3d curve)
1178   if (ExchUV) {
1179     PC = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));
1180     U1 = f1;
1181     U2 = l1;
1182     if (!C2is3D) C2 = S->VIso(l2);
1183   }
1184   else {
1185     PC = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));
1186     U1 = f2;
1187     U2 = l2;
1188     if (!C2is3D) C2 = S->UIso(l1);
1189   }
1190
1191   if (!C2is3D)
1192     UpdateEdge(Edge2,C2,Id,BRep_Tool::Tolerance(Edge2));
1193   else if ( C2Denerated) {
1194     UpdateEdge(Edge2,Dummy,Id,BRep_Tool::Tolerance(Edge2));
1195     myBuilder.Degenerated(Edge2,Standard_True);
1196   }
1197
1198   TheTol = Max(PathTol, BRep_Tool::Tolerance(Edge2) + ErrorPipe);
1199   UpdateEdge(Edge2, PC, myFace, TheTol);
1200
1201   // mise a same range de la nouvelle pcurve.
1202   myBuilder.SameRange    (Edge2,Standard_False);
1203   if ( !C2is3D && !C2Denerated)
1204     myBuilder.Range(Edge2, U1, U2, Standard_True);
1205   myBuilder.Range(Edge2,myFace,U1,U2);
1206   BRepLib::SameRange(Edge2);
1207   
1208   // mise a sameparameter pour les KPart
1209   if (ErrorPipe == 0) {
1210    TheTol = Max(TheTol, Tol); 
1211     myBuilder.SameParameter(Edge2,Standard_False);
1212     BRepLib::SameParameter(Edge2, TheTol);
1213   }
1214
1215   TopoDS_Edge Edge3, Edge4;
1216   // eval edge3
1217   TopoDS_Vertex V1f,V1l,V2f,V2l;
1218   TopExp::Vertices(Path,V1f,V1l);
1219   Standard_Boolean IsClosed = ( V1f.IsSame(V1l));
1220
1221   TopExp::Vertices(Edge1,V1f,V1l);
1222   TopExp::Vertices(Edge2,V2f,V2l);
1223
1224   Standard_Boolean StartDegenerated = (V1f.IsSame(V2f));
1225   Standard_Boolean EndDegenerated   = (V1l.IsSame(V2l));
1226
1227   Standard_Boolean E3rev = Standard_False;
1228   Standard_Boolean E4rev = Standard_False;
1229   
1230   TopoDS_Vertex VVf,VVl;
1231   if ( FirstEdge.IsNull()) {
1232     myBuilder.MakeEdge(Edge3);
1233     myBuilder.Add(Edge3,V1f.Oriented(TopAbs_FORWARD));
1234     myBuilder.Add(Edge3,V2f.Oriented(TopAbs_REVERSED));
1235   }
1236   else {
1237     TopoDS_Shape aLocalEdge = FirstEdge.Oriented(TopAbs_FORWARD);
1238     Edge3 = TopoDS::Edge(aLocalEdge);
1239 //    Edge3 = TopoDS::Edge(FirstEdge.Oriented(TopAbs_FORWARD));
1240     TopExp::Vertices(Edge3,VVf,VVl);
1241 #ifdef OCCT_DEBUG
1242     // si firstedge n est pas nul, il faut que les vertex soient partages
1243     if ( !VVf.IsSame(V1f) && !VVf.IsSame(V2f) ) {
1244       std::cout << "Attention Vertex non partages !!!!!!" << std::endl;
1245     }    
1246 #endif
1247     if ( !VVf.IsSame(V1f) && !VVf.IsSame(V2f) ) {
1248       // On fait vraisemblablement des conneries !!
1249       // On cree un autre edge, on appelle le Sewing apres.
1250       myBuilder.MakeEdge(Edge3);
1251       myBuilder.Add(Edge3,V1f.Oriented(TopAbs_FORWARD));
1252       myBuilder.Add(Edge3,V2f.Oriented(TopAbs_REVERSED));
1253     }
1254     else if ( !VVf.IsSame(V1f)) {
1255       Edge3.Reverse();
1256       E3rev = Standard_True;
1257     }
1258   }
1259
1260   if ( IsClosed)
1261     Edge4 = Edge3;
1262
1263   Standard_Real TolApp = Precision::Approximation();
1264
1265   Handle(Geom2d_Line) L1,L2;
1266   if ( IsClosed) {
1267     if ( ExchUV) {
1268       // rem : si ExchUv, il faut  reverser le Wire. 
1269       // donc l'edge Forward dans la face sera E4 : d'ou L1 et L2
1270       L2 = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1271       L1 = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));
1272       U1 = f2;
1273       U2 = l2;
1274     }
1275     else {
1276       L1 = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1277       L2 = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));
1278       U1 = f1;
1279       U2 = l1;
1280     }
1281     if ( E3rev) {
1282       L1->Reverse(); L2->Reverse();
1283       U  = -U1;
1284       U1 = -U2;
1285       U2 =  U;
1286     }
1287     UpdateEdge(Edge3, L1, L2, myFace,PathTol);
1288     myBuilder.Range(Edge3,myFace,U1,U2);
1289     if (StartDegenerated) 
1290       myBuilder.Degenerated(Edge3,Standard_True);
1291     else if (FirstEdge.IsNull()) // then the 3d curve has not been yet computed
1292       ComputeCurve3d(Edge3,L1,S,Id,TolApp);
1293   }
1294   else {
1295     if ( LastEdge.IsNull()) {
1296       myBuilder.MakeEdge(Edge4);
1297       myBuilder.Add(Edge4,V1l.Oriented(TopAbs_FORWARD));
1298       myBuilder.Add(Edge4,V2l.Oriented(TopAbs_REVERSED));
1299     }
1300     else {
1301       TopoDS_Shape aLocalEdge = LastEdge.Oriented(TopAbs_FORWARD);
1302       Edge4 = TopoDS::Edge(aLocalEdge);
1303 //      Edge4 = TopoDS::Edge(LastEdge.Oriented(TopAbs_FORWARD));
1304       TopExp::Vertices(Edge4,VVf,VVl);
1305 #ifdef OCCT_DEBUG
1306       // si lastedge n est pas nul, il faut que les vertex soient partages
1307       if ( !VVf.IsSame(V1l) && !VVf.IsSame(V2l) ) {
1308         std::cout << "Attention Vertex non partages !!!!!!" << std::endl;
1309       }    
1310 #endif
1311       if ( !VVf.IsSame(V1l) && !VVf.IsSame(V2l) ) {
1312         // On fait vraisemblablement des conneries !!
1313         // On cree un autre edge, on appelle le Sewing apres.
1314         myBuilder.MakeEdge(Edge4);
1315         myBuilder.Add(Edge4,V1l.Oriented(TopAbs_FORWARD));
1316         myBuilder.Add(Edge4,V2l.Oriented(TopAbs_REVERSED));
1317       }
1318       else if ( !VVf.IsSame(V1l)) {
1319         Edge4.Reverse();
1320         E4rev = Standard_True;
1321       }
1322     }
1323
1324     if (ExchUV) {
1325       L1 = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1326       U1 = f2;
1327       U2 = l2;
1328     }
1329     else {
1330       L1 = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1331       U1 = f1;
1332       U2 = l1;
1333     }
1334     if ( E3rev) {
1335       L1->Reverse();
1336       U  = -U1;
1337       U1 = -U2;
1338       U2 =  U;
1339     }
1340     UpdateEdge(Edge3,L1,myFace,PathTol);
1341     myBuilder.Range(Edge3,myFace,U1,U2);
1342     if (StartDegenerated) 
1343       myBuilder.Degenerated(Edge3,Standard_True);
1344     else if (FirstEdge.IsNull()) // then the 3d curve has not been yet computed
1345       ComputeCurve3d(Edge3,L1,S,Id,TolApp);
1346
1347     if (ExchUV) {
1348       L2 = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));    
1349       U1 = f2;
1350       U2 = l2;
1351     }
1352     else {
1353       L2 = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));    
1354       U1 = f1;
1355       U2 = l1;
1356     }
1357     if ( E4rev) {
1358       L2->Reverse();
1359       U  = -U1;
1360       U1 = -U2;
1361       U2 =  U;
1362     }
1363     UpdateEdge(Edge4,L2 ,myFace,PathTol);
1364     myBuilder.Range(Edge4,myFace,U1,U2);   
1365     if (EndDegenerated) 
1366       myBuilder.Degenerated(Edge4,Standard_True);
1367     else if (LastEdge.IsNull()) // then the 3d curve has not been yet computed
1368       ComputeCurve3d(Edge4,L2,S,Id,TolApp);
1369   }
1370   
1371   // SameParameter ??
1372   if ( !FirstEdge.IsNull() && !StartDegenerated) {
1373     BRepLib::BuildCurve3d  (Edge3,PathTol);
1374     myBuilder.SameRange    (Edge3,Standard_False);
1375     myBuilder.SameParameter(Edge3,Standard_False);
1376     BRepLib::SameParameter (Edge3, Tol);
1377   }
1378   if ( !LastEdge.IsNull() && !EndDegenerated) {
1379     BRepLib::BuildCurve3d  (Edge4,PathTol);
1380     myBuilder.SameRange    (Edge4,Standard_False);
1381     myBuilder.SameParameter(Edge4,Standard_False);
1382     BRepLib::SameParameter (Edge4, Tol);
1383   }
1384
1385   TopoDS_Wire W;
1386   myBuilder.MakeWire(W);
1387   
1388   myBuilder.Add(W, Edge1.Oriented(TopAbs_REVERSED));
1389   myBuilder.Add(W, Edge2.Oriented(TopAbs_FORWARD));
1390   myBuilder.Add(W, Edge4.Reversed());
1391   myBuilder.Add(W, Edge3);
1392
1393   if (ExchUV) { 
1394     W.Reverse();
1395   }    
1396
1397   myBuilder.Add(myFace, W);
1398   if (ExchUV) myFace.Reverse();
1399
1400   BRepTools::Update(myFace);
1401
1402   if ( Edge1.Orientation() == TopAbs_REVERSED)
1403     myFace.Reverse();
1404
1405 }
1406
1407
1408 //=======================================================================
1409 //function : Init
1410 //purpose  : 
1411 //=======================================================================
1412
1413 void BRepOffset_Offset::Init(const TopoDS_Vertex&        Vertex,
1414                              const TopTools_ListOfShape& LEdge,
1415                              const Standard_Real         Offset,
1416                              const Standard_Boolean      Polynomial,
1417                              const Standard_Real         TolApp,
1418                              const GeomAbs_Shape         Conti)
1419 {
1420   myStatus = BRepOffset_Good;
1421   myShape = Vertex;
1422
1423   // evaluate the Ax3 of the Sphere
1424   // find 3 different vertices in LEdge
1425   TopTools_ListIteratorOfListOfShape it;
1426   gp_Pnt P, P1, P2, P3;
1427   TopoDS_Vertex V1, V2, V3, V4;
1428
1429
1430 #ifdef OCCT_DEBUG
1431   char* name = new char[100];
1432   if (Affich) {
1433     NbOFFSET++;
1434     
1435     sprintf(name,"VOnSph_%d",NbOFFSET);
1436 #ifdef DRAW
1437     DBRep::Set(name, Vertex);
1438 #endif
1439     Standard_Integer NbEdges = 1;
1440     for (it.Initialize(LEdge); it.More(); it.Next()) {
1441       sprintf(name,"EOnSph_%d_%d",NbOFFSET,NbEdges++);
1442 #ifdef DRAW
1443       const TopoDS_Shape& CurE = it.Value();
1444       DBRep::Set(name, CurE);
1445 #endif
1446     }
1447
1448   }
1449 #endif
1450
1451   gp_Pnt Origin = BRep_Tool::Pnt(Vertex);
1452
1453   //// Find the axis of the sphere to exclude
1454   //// degenerated and seam edges from the face under construction
1455   BRepLib_MakeWire MW;
1456   MW.Add(LEdge);
1457   TopoDS_Wire theWire = MW.Wire();
1458
1459   ShapeFix_Shape Fixer(theWire);
1460   Fixer.Perform();
1461   theWire = TopoDS::Wire(Fixer.Shape());
1462
1463   GProp_GProps GlobalProps;
1464   BRepGProp::LinearProperties(theWire, GlobalProps);
1465   gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
1466   gp_Vec Xdir(BaryCenter, Origin);
1467
1468   gp_Pnt FarestCorner = GetFarestCorner(theWire);
1469   gp_Pln thePlane = gce_MakePln(Origin, BaryCenter, FarestCorner);
1470   gp_Dir Vdir = thePlane.Axis().Direction();
1471
1472   gp_Ax3 Axis(Origin, Vdir, Xdir);
1473   
1474   Handle(Geom_Surface) S 
1475     = new Geom_SphericalSurface( Axis, Abs(Offset));
1476
1477   Standard_Real f, l, Tol = BRep_Tool::Tolerance(Vertex);
1478   
1479   TopLoc_Location Loc;
1480   BRep_Builder myBuilder;
1481   myBuilder.MakeFace(myFace);
1482   Handle(Geom_Surface) SS = S;
1483
1484   // En polynomial, calcul de la surface par F(u,v).
1485   // Pas de changement de parametre, donc ProjLib sur la Sphere
1486   // reste OK.
1487   if (Polynomial) {
1488     GeomConvert_ApproxSurface Approx(S,TolApp,Conti,Conti,10,10,10,1);
1489     if (Approx.IsDone()) {
1490       SS = Approx.Surface();
1491     }
1492   }
1493
1494   myBuilder.UpdateFace(myFace, SS, Loc, Tol);
1495   
1496   TopoDS_Wire W;
1497   myBuilder.MakeWire(W);
1498   
1499 #ifdef DRAW
1500   // POP pour NT
1501   //  char name[100];
1502   if (Affich) {
1503     sprintf(name,"SPHERE_%d",NbOFFSET);
1504     DrawTrSurf::Set(name, S);
1505   }
1506   Standard_Integer CO = 1;
1507 #endif
1508
1509   for ( it.Initialize(LEdge); it.More(); it.Next()) {
1510     TopoDS_Edge E = TopoDS::Edge(it.Value());
1511
1512     Handle(Geom_Curve) C = BRep_Tool::Curve(E,Loc,f,l);
1513     if ( C.IsNull()) {
1514       BRepLib::BuildCurve3d(E,BRep_Tool::Tolerance(E));
1515       C = BRep_Tool::Curve(E,Loc,f,l);
1516     }
1517     C = new Geom_TrimmedCurve(C, f, l);
1518     C->Transform(Loc.Transformation());
1519
1520 #ifdef DRAW
1521     if ( Affich) {
1522       sprintf(name,"CURVE_%d_%d",NbOFFSET,CO);
1523       DrawTrSurf::Set(name, C);
1524       CO++;
1525     }
1526 #endif
1527
1528     Handle(Geom2d_Curve) PCurve = GeomProjLib::Curve2d(C, S);
1529     // check if the first point of PCurve in is the canonical boundaries 
1530     // of the sphere. Else move it.
1531     // the transformation is : U` = U + PI + 2 k  PI
1532     //                         V` = +/- PI + 2 k` PI
1533     gp_Pnt2d P2d = PCurve->Value(f);
1534     Standard_Boolean IsToAdjust = Standard_False;
1535     if ( P2d.Y() < -M_PI/2.) {
1536       IsToAdjust = Standard_True;
1537       PCurve->Mirror(gp_Ax2d(gp_Pnt2d(0.,-M_PI/2.),gp::DX2d()));
1538     }
1539     else if ( P2d.Y() > M_PI/2.) {
1540       IsToAdjust = Standard_True;
1541       PCurve->Mirror(gp_Ax2d(gp_Pnt2d(0., M_PI/2.),gp::DX2d()));
1542     }
1543     if ( IsToAdjust) {
1544       // set the u firstpoint in [0,2*pi]
1545       gp_Vec2d Tr( M_PI, 0.);
1546       if ( P2d.X() > M_PI) Tr.Reverse();
1547       PCurve->Translate(Tr);
1548     }
1549
1550     UpdateEdge(E, PCurve, myFace, Tol);
1551     myBuilder.Range(E, myFace, f, l);
1552     myBuilder.Add(W, E);
1553   }
1554   if ( Offset < 0.) {
1555     myBuilder.Add(myFace, W.Oriented(TopAbs_REVERSED));
1556     myFace.Reverse();
1557   }
1558   else {
1559     myBuilder.Add(myFace, W);
1560   }
1561
1562   BRepTools::Update(myFace);
1563 }
1564
1565
1566 //=======================================================================
1567 //function : Init
1568 //purpose  : 
1569 //=======================================================================
1570
1571 void BRepOffset_Offset::Init(const TopoDS_Edge&  Edge,
1572                              const Standard_Real Offset)
1573 {
1574   myShape   = Edge;
1575   Standard_Real myOffset = Abs(Offset);
1576
1577   Standard_Real f,l;
1578   TopLoc_Location Loc;
1579
1580   Handle(Geom_Curve) CP = BRep_Tool::Curve(Edge,Loc,f,l);
1581   CP = new Geom_TrimmedCurve(CP,f,l);
1582   CP->Transform(Loc.Transformation());
1583
1584   GeomFill_Pipe Pipe(CP,myOffset);
1585   Pipe.Perform();
1586   if (!Pipe.IsDone())
1587     throw Standard_ConstructionError("GeomFill_Pipe : Cannot make a surface");
1588
1589   BRepLib_MakeFace MF(Pipe.Surface(), Precision::Confusion());
1590   myFace = MF.Face();
1591
1592   if ( Offset < 0.) myFace.Reverse();
1593 }
1594
1595
1596 //=======================================================================
1597 //function : Face
1598 //purpose  : 
1599 //=======================================================================
1600
1601 const TopoDS_Face& BRepOffset_Offset::Face() const 
1602 {
1603   return myFace;
1604 }
1605
1606
1607 //=======================================================================
1608 //function : Generated
1609 //purpose  : 
1610 //=======================================================================
1611
1612 TopoDS_Shape BRepOffset_Offset::Generated(const TopoDS_Shape& Shape) const 
1613 {
1614   TopoDS_Shape aShape;
1615
1616   switch ( myShape.ShapeType())
1617   {
1618     case TopAbs_FACE:
1619     {
1620       TopExp_Explorer exp  (myShape.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1621       TopExp_Explorer expo (myFace .Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1622       for (; exp.More() && expo.More(); exp.Next(), expo.Next())
1623       {
1624         if (Shape.IsSame (exp.Current()))
1625         {
1626           if (myShape.Orientation() == TopAbs_REVERSED)
1627             aShape = expo.Current().Reversed();
1628           else
1629             aShape = expo.Current();
1630           break;
1631         }
1632       }
1633     }
1634     break;
1635
1636     case TopAbs_EDGE:
1637     // have generate a pipe.
1638     {
1639       TopoDS_Vertex V1, V2;
1640       TopExp::Vertices(TopoDS::Edge(myShape), V1, V2);
1641
1642       TopExp_Explorer expf(myFace.Oriented(TopAbs_FORWARD), TopAbs_WIRE);
1643       TopExp_Explorer expo(expf.Current().Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1644       expo.Next(); 
1645       expo.Next();
1646       
1647       if ( V2.IsSame(Shape)) {
1648         if (expf.Current().Orientation() == TopAbs_REVERSED)
1649           aShape = expo.Current().Reversed();
1650         else
1651           aShape = expo.Current();
1652       }
1653       else {
1654         expo.Next();
1655         if (expf.Current().Orientation() == TopAbs_REVERSED)
1656           aShape = expo.Current().Reversed();
1657         else
1658           aShape = expo.Current();
1659       }
1660       if (myFace.Orientation() == TopAbs_REVERSED)
1661         aShape.Reverse();
1662     }
1663     break;
1664   default:
1665     break;
1666   }
1667
1668   return aShape;
1669 }
1670
1671
1672 //=======================================================================
1673 //function : Status
1674 //purpose  : 
1675 //=======================================================================
1676
1677 BRepOffset_Status BRepOffset_Offset::Status() const 
1678 {
1679   return myStatus;
1680 }