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