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