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