0024023: Revamp the OCCT Handle - gcc and clang
[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           if (BRep_Tool::Degenerated(anEdge))
543             DegEdges.Append(anEdge);
544         }
545       if (!DegEdges.IsEmpty())
546         {
547           const Standard_Real TolApex = 1.e-5;
548           //define the iso of singularity (u or v)
549           const TopoDS_Edge& theDegEdge = TopoDS::Edge(DegEdges(1));
550           Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(theDegEdge, Face, fpar, lpar);
551           gp_Pnt2d fp2d = aCurve->Value(fpar);
552           gp_Pnt2d lp2d = aCurve->Value(lpar);
553           if (Abs(fp2d.X() - lp2d.X()) <= Precision::PConfusion())
554             UisoDegen = Standard_True;
555
556           if (DegEdges.Length() == 2)
557             {
558               if (UisoDegen)
559               { UminDegen = Standard_True; UmaxDegen = Standard_True; }
560               else
561               { VminDegen = Standard_True; VmaxDegen = Standard_True; }
562             }
563           else //DegEdges.Length() == 1
564             {
565               const TopoDS_Edge& theDegEdge = TopoDS::Edge(DegEdges(1));
566               Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(theDegEdge, Face, fpar, lpar);
567               if (UisoDegen)
568               {
569                 if (Abs(fp2d.X() - uf1) <= Precision::Confusion())
570                   UminDegen = Standard_True;
571                 else
572                   UmaxDegen = Standard_True;
573               }
574               else
575               {
576                 if (Abs(fp2d.Y() - vf1) <= Precision::Confusion())
577                   VminDegen = Standard_True;
578                 else
579                   VmaxDegen = Standard_True;
580               }
581             }
582           if (TheSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
583             {
584               gp_Cone theCone = Handle(Geom_ConicalSurface)::DownCast (TheSurf)->Cone();
585               gp_Pnt apex = theCone.Apex();
586               Standard_Real Uapex, Vapex;
587               ElSLib::Parameters( theCone, apex, Uapex, Vapex );
588               if (VminDegen)
589                 {
590                   TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, Vapex, vf2);
591                   MinApex = apex;
592                   HasSingularity = Standard_True;
593                 }
594               else if (VmaxDegen)
595                 {
596                   TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, Vapex);
597                   MaxApex = apex;
598                   HasSingularity = Standard_True;
599                 }
600             }
601           else //TheSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)
602             {
603               if (UminDegen)
604               {
605                 Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
606                 if (BRepOffset_Tool::Gabarit( uiso ) > TolApex)
607                 {
608                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
609                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
610                   Papex = BasisSurf->Value( uf1, vf1 );
611                   Pfirst = TheSurf->Value( uf1, vf1 );
612                   Pquart = TheSurf->Value( uf1, 0.75*vf1+0.25*vf2 );
613                   Pmid   = TheSurf->Value( uf1, 0.5*(vf1+vf2) );
614                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
615                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
616                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf1, 1, 0 );
617                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
618                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
619                   gp_Pnt Pint1, Pint2;
620                   theExtrema.NearestPoints(Pint1, Pint2);
621                   Standard_Real length = Pfirst.Distance(Pint1);
622                   if (OffsetOutside)
623                   {
624                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
625                     GeomLib::ExtendSurfByLength (aSurf, length, 1, Standard_True, Standard_False);
626                     TheSurf = aSurf;
627                     Standard_Real u1, u2, v1, v2;
628                     TheSurf->Bounds( u1, u2, v1, v2 );
629                     MinApex = TheSurf->Value( u1, vf1 );
630                   }
631                   else
632                   {
633                     Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
634                     GeomAPI_ProjectPointOnCurve Projector( Pint1, viso );
635                     Standard_Real NewFirstU = Projector.LowerDistanceParameter();
636                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, NewFirstU, uf2, vf1, vf2);
637                     MinApex = TheSurf->Value( NewFirstU, vf1 );
638                   }
639                   HasSingularity = Standard_True;
640                 }
641               } //end of if (UminDegen)
642               if (UmaxDegen)
643               {
644                 Handle(Geom_Curve) uiso = TheSurf->UIso( uf2 );
645                 if (BRepOffset_Tool::Gabarit( uiso ) > TolApex)
646                 {
647                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
648                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
649                   Papex  = BasisSurf->Value( uf2, vf1 );
650                   Pfirst = TheSurf->Value( uf2, vf1 );
651                   Pquart = TheSurf->Value( uf2, 0.75*vf1+0.25*vf2 );
652                   Pmid   = TheSurf->Value( uf2, 0.5*(vf1+vf2) );
653                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
654                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
655                   gp_Vec DirGeneratrix = BasisSurf->DN( uf2, vf1, 1, 0 );
656                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
657                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
658                   gp_Pnt Pint1, Pint2;
659                   theExtrema.NearestPoints(Pint1, Pint2);
660                   Standard_Real length = Pfirst.Distance(Pint1);
661                   if (OffsetOutside)
662                   {
663                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
664                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_True, Standard_True);
665                     TheSurf = aSurf;
666                     Standard_Real u1, u2, v1, v2;
667                     TheSurf->Bounds( u1, u2, v1, v2 );
668                     MaxApex = TheSurf->Value( u2, vf1 );
669                   }
670                   else
671                   {
672                     Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
673                     GeomAPI_ProjectPointOnCurve Projector( Pint1, viso );
674                     Standard_Real NewLastU = Projector.LowerDistanceParameter();
675                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, NewLastU, vf1, vf2);
676                     MaxApex = TheSurf->Value( NewLastU, vf1 );
677                   }
678                   HasSingularity = Standard_True;
679                 }
680               } //end of if (UmaxDegen)
681               if (VminDegen)
682               {
683                 Handle(Geom_Curve) viso = TheSurf->VIso( vf1 );
684                 if (BRepOffset_Tool::Gabarit( viso ) > TolApex)
685                 {
686                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
687                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
688                   Papex = BasisSurf->Value( uf1, vf1 );
689                   Pfirst = TheSurf->Value( uf1, vf1 );
690                   Pquart = TheSurf->Value( 0.75*uf1+0.25*uf2, vf1 );
691                   Pmid   = TheSurf->Value( 0.5*(uf1+uf2), vf1 );
692                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
693                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
694                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf1, 0, 1 );
695                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
696                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
697                   gp_Pnt Pint1, Pint2;
698                   theExtrema.NearestPoints(Pint1, Pint2);
699                   Standard_Real length = Pfirst.Distance(Pint1);
700                   if (OffsetOutside)
701                   {
702                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
703                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_False, Standard_False);
704                     TheSurf = aSurf;
705                     Standard_Real u1, u2, v1, v2;
706                     TheSurf->Bounds( u1, u2, v1, v2 );
707                     MinApex = TheSurf->Value( uf1, v1 );
708                   }
709                   else
710                   {
711                     Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
712                     GeomAPI_ProjectPointOnCurve Projector( Pint1, uiso );
713                     Standard_Real NewFirstV = Projector.LowerDistanceParameter();
714                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, NewFirstV, vf2);
715                     MinApex = TheSurf->Value( uf1, NewFirstV );
716                     //TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1+length, vf2);
717                     //MinApex = TheSurf->Value( uf1, vf1+length );
718                   }
719                   HasSingularity = Standard_True;
720                 }
721               } //end of if (VminDegen)
722               if (VmaxDegen)
723               {
724                 Handle(Geom_Curve) viso = TheSurf->VIso( vf2 );
725                 if (BRepOffset_Tool::Gabarit( viso ) > TolApex)
726                 {
727                   Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (TheSurf)->BasisSurface();
728                   gp_Pnt Papex, Pfirst, Pquart, Pmid;
729                   Papex = BasisSurf->Value( uf1, vf2 );
730                   Pfirst = TheSurf->Value( uf1, vf2 );
731                   Pquart = TheSurf->Value( 0.75*uf1+0.25*uf2, vf2 );
732                   Pmid   = TheSurf->Value( 0.5*(uf1+uf2), vf2 );
733                   gp_Vec DirApex = gp_Vec(Pfirst,Pquart) ^ gp_Vec(Pfirst,Pmid);
734                   Handle(Geom_Line) LineApex = new Geom_Line( Papex, DirApex );
735                   gp_Vec DirGeneratrix = BasisSurf->DN( uf1, vf2, 0, 1 );
736                   Handle(Geom_Line) LineGeneratrix = new Geom_Line( Pfirst, DirGeneratrix );
737                   GeomAPI_ExtremaCurveCurve theExtrema( LineGeneratrix, LineApex );
738                   gp_Pnt Pint1, Pint2;
739                   theExtrema.NearestPoints(Pint1, Pint2);
740                   Standard_Real length = Pfirst.Distance(Pint1);
741                   if (OffsetOutside)
742                   {
743                     Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2);
744                     GeomLib::ExtendSurfByLength(aSurf, length, 1, Standard_False, Standard_True);
745                     TheSurf = aSurf;
746                     Standard_Real u1, u2, v1, v2;
747                     TheSurf->Bounds( u1, u2, v1, v2 );
748                     MaxApex = TheSurf->Value( uf1, v2 );
749                   }
750                   else
751                   {
752                     Handle(Geom_Curve) uiso = TheSurf->UIso( uf1 );
753                     GeomAPI_ProjectPointOnCurve Projector( Pint1, uiso );
754                     Standard_Real NewLastV = Projector.LowerDistanceParameter();
755                     TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, NewLastV);
756                     MaxApex = TheSurf->Value( uf1, NewLastV );
757                     //TheSurf = new Geom_RectangularTrimmedSurface(TheSurf, uf1, uf2, vf1, vf2-length);
758                     //MaxApex = TheSurf->Value( uf1, vf2-length );
759                   }
760                   HasSingularity = Standard_True;
761                 }
762               } //end of if (VmaxDegen)
763             } //end of else (case of Geom_OffsetSurface)
764         } //end of if (!DegEdges.IsEmpty())
765     } //end of processing offsets of faces with possible degenerated edges
766   
767   // find the PCurves of the edges of <Faces> 
768
769   BRep_Builder myBuilder;
770   myBuilder.MakeFace(myFace);
771   myBuilder.UpdateFace(myFace,TheSurf,L,BRep_Tool::Tolerance(Face));
772
773   TopTools_DataMapOfShapeShape MapSS;
774
775   // mise a jour de la map sur les vertex deja crees
776   TopoDS_Shape aLocalShape = Face.Oriented(TopAbs_FORWARD);
777   TopoDS_Face CurFace = TopoDS::Face(aLocalShape);
778 //  TopoDS_Face CurFace = TopoDS::Face(Face.Oriented(TopAbs_FORWARD));
779
780   TopTools_MapOfShape VonDegen;
781   Standard_Real u1, u2, v1, v2;
782   TheSurf->Bounds( u1, u2, v1, v2 );
783
784   TopExp_Explorer exp(CurFace, TopAbs_EDGE);
785   for ( ; exp.More(); exp.Next()) {
786     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
787     TopoDS_Vertex V1,V2,OV1,OV2;
788     TopExp::Vertices(E ,V1 ,V2 );
789     if (HasSingularity && BRep_Tool::Degenerated(E))
790       VonDegen.Add( V1 );
791     if (Created.IsBound(E)) {
792       const TopoDS_Edge& OE = TopoDS::Edge(Created(E));
793       TopExp::Vertices(OE,OV1,OV2);
794       if (!MapSS.IsBound(V1)) MapSS.Bind(V1,OV1);
795       if (!MapSS.IsBound(V2)) MapSS.Bind(V2,OV2);
796     }
797     if (Created.IsBound(V1)) {
798       if (!MapSS.IsBound(V1)) MapSS.Bind(V1,Created(V1));
799     }
800     if (Created.IsBound(V2)) {
801       if (!MapSS.IsBound(V2)) MapSS.Bind(V2,Created(V2));
802     }
803   }
804
805   TopExp_Explorer expw(CurFace, TopAbs_WIRE);
806   for ( ; expw.More(); expw.Next()) {
807     const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
808     TopExp_Explorer expe(W.Oriented(TopAbs_FORWARD),
809                          TopAbs_EDGE);
810     TopoDS_Wire OW;
811     myBuilder.MakeWire(OW);
812     for ( ; expe.More(); expe.Next()) {
813       const TopoDS_Edge& E = TopoDS::Edge(expe.Current());
814       TopoDS_Vertex V1,V2;
815       TopExp::Vertices(E,V1,V2);
816       gp_Pnt2d P2d1, P2d2;
817       gp_Pnt P1, P2;
818       Standard_Real vstart, vend;
819       Standard_Real f,l;
820       Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E,CurFace,f,l);
821       TopoDS_Edge OE;
822       if (MapSS.IsBound(E) &&
823           !VonDegen.Contains(V1) && !VonDegen.Contains(V2)) { // c`est un edge de couture 
824         OE = TopoDS::Edge(MapSS(E));
825         TopoDS_Shape aLocalShape = E.Reversed();
826         Handle(Geom2d_Curve) C2d_1 = 
827           BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShape),CurFace,f,l);
828 //      Handle(Geom2d_Curve) C2d_1 = 
829 //        BRep_Tool::CurveOnSurface(TopoDS::Edge(E.Reversed()),CurFace,f,l);
830         if ( E.Orientation() == TopAbs_FORWARD)
831           UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
832         else
833           UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
834         myBuilder.Range(OE,f,l);
835       }
836       else {
837         TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
838         TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape);
839         P2d1 = C2d->Value(BRep_Tool::Parameter(V1,Eforward,CurFace));
840         P2d2 = C2d->Value(BRep_Tool::Parameter(V2,Eforward,CurFace));
841         if (VonDegen.Contains(V1))
842           {
843             if (Abs(P2d1.Y() - vf1) <= Precision::Confusion())
844               {
845                 P1 = MinApex; vstart = v1;
846               }
847             else
848               {
849                 P1 = MaxApex; vstart = v2;
850               }
851           }
852         else
853           {
854             TheSurf->D0(P2d1.X(),P2d1.Y(),P1);
855             P1.Transform(L.Transformation());
856             vstart = P2d1.Y();
857           }
858         if (VonDegen.Contains(V2))
859           {
860             if (Abs(P2d2.Y() - vf1) <= Precision::Confusion())
861               {
862                 P2 = MinApex; vend = v1;
863               }
864             else
865               {
866                 P2 = MaxApex; vend = v2;
867               }
868           }
869         else
870           {
871             TheSurf->D0(P2d2.X(),P2d2.Y(),P2);
872             P2.Transform(L.Transformation());
873             vend = P2d2.Y();
874           }
875         // E a-t-il ume image dans la Map des Created ?
876         if ( Created.IsBound(E)) {
877           OE = TopoDS::Edge(Created(E));
878         }
879         else if (MapSS.IsBound(E)) //seam edge
880           OE = TopoDS::Edge(MapSS(E));
881         else {
882           myBuilder.MakeEdge(OE);
883           TopoDS_Vertex OV1,OV2;
884           if ( MapSS.IsBound(V1)) {
885             OV1 = TopoDS::Vertex(MapSS(V1));
886           }
887           else {
888             myBuilder.MakeVertex(OV1);
889             myBuilder.UpdateVertex(OV1,P1,BRep_Tool::Tolerance(V1));
890             MapSS.Bind(V1,OV1);
891           }
892           if ( MapSS.IsBound(V2)) {
893             OV2 = TopoDS::Vertex(MapSS(V2));
894           }
895           else {
896             myBuilder.MakeVertex(OV2);
897             myBuilder.UpdateVertex(OV2,P2,BRep_Tool::Tolerance(V2));
898             MapSS.Bind(V2,OV2);
899           }
900           myBuilder.Add(OE,OV1.Oriented(V1.Orientation()));
901           myBuilder.Add(OE,OV2.Oriented(V2.Orientation()));
902           if (BRep_Tool::Degenerated(E)) {
903             myBuilder.Degenerated(OE, Standard_True);
904             /*
905 #ifdef OCCT_DEBUG
906             gp_Pnt        P1,P2;
907             gp_Pnt2d      P2d;
908             P2d = C2d->Value(f); TheSurf->D0(P2d.X(),P2d.Y(),P1);
909             P2d = C2d->Value(l); TheSurf->D0(P2d.X(),P2d.Y(),P2);         
910             Standard_Real Tol = BRep_Tool::Tolerance(V1); 
911             if (!P1.IsEqual(P2,Tol)) {
912               cout <<"BRepOffset_Offset : E degenerated -> OE not degenerated"<<endl; 
913             }
914 #endif    
915             */
916           }
917         }
918         if (VonDegen.Contains(V1) || VonDegen.Contains(V2))
919           {
920             if (VonDegen.Contains(V1))
921               P2d1.SetY( vstart );
922             if (VonDegen.Contains(V2))
923               P2d2.SetY( vend );
924             C2d = new Geom2d_Line( P2d1, gp_Vec2d(P2d1, P2d2) );
925             f = 0.; l = P2d1.Distance( P2d2 );
926             if (MapSS.IsBound(E)) //seam edge
927               {
928                 Handle(Geom2d_Curve) C2d_1 = BRep_Tool::CurveOnSurface(OE, myFace, f, l);
929                 if (E.Orientation() == TopAbs_FORWARD)
930                   UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
931                 else
932                   UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
933               }
934             else
935               UpdateEdge(OE,C2d,myFace,BRep_Tool::Tolerance(E));
936             //myBuilder.Range(OE,f,l);
937             myBuilder.Range(OE, myFace, f, l);
938             if (!BRep_Tool::Degenerated(E) && TheSurf->IsUClosed())
939               {
940                 TopoDS_Shape aLocalShape = E.Reversed();
941                 Handle(Geom2d_Curve) C2d_1 = 
942                   BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalShape),CurFace,f,l);
943                 P2d1 = C2d_1->Value(BRep_Tool::Parameter(V1,E,CurFace));
944                 P2d2 = C2d_1->Value(BRep_Tool::Parameter(V2,E,CurFace));
945                 if (VonDegen.Contains(V1))
946                   P2d1.SetY( vstart );
947                 if (VonDegen.Contains(V2))
948                   P2d2.SetY( vend );
949                 C2d_1 = new Geom2d_Line( P2d1, gp_Vec2d(P2d1, P2d2) );
950                 if ( E.Orientation() == TopAbs_FORWARD)
951                   UpdateEdge(OE,C2d,C2d_1,myFace,BRep_Tool::Tolerance(E));
952                 else
953                   UpdateEdge(OE,C2d_1,C2d,myFace,BRep_Tool::Tolerance(E));
954               }
955             /*
956             if (!BRep_Tool::Degenerated(E))
957               {
958                 Handle(Geom_Line) theLine = new Geom_Line( P1, gp_Vec(P1, P2) );
959                 myBuilder.UpdateEdge( OE, theLine, BRep_Tool::Tolerance(E) );
960               }
961             */
962           }
963         else
964           {
965             UpdateEdge(OE,C2d,myFace,BRep_Tool::Tolerance(E));
966             myBuilder.Range(OE,f,l);
967             //ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
968           }
969         if (!BRep_Tool::Degenerated(OE))
970           ComputeCurve3d(OE,C2d,TheSurf,L,BRep_Tool::Tolerance(E));
971         MapSS.Bind(E,OE);
972       }
973       myBuilder.Add(OW, OE.Oriented(E.Orientation()));
974     }
975     myBuilder.Add(myFace, OW.Oriented(W.Orientation()));
976   }
977
978   myFace.Orientation(Face.Orientation());
979   
980   BRepTools::Update(myFace);
981 }
982
983
984 //=======================================================================
985 //function : Init
986 //purpose  : 
987 //=======================================================================
988
989 void BRepOffset_Offset::Init(const TopoDS_Edge&     Path,
990                              const TopoDS_Edge&     Edge1,
991                              const TopoDS_Edge&     Edge2, 
992                              const Standard_Real    Offset,
993                              const Standard_Boolean Polynomial,
994                              const Standard_Real    Tol,
995                              const GeomAbs_Shape    Conti)
996 {
997   TopoDS_Edge FirstEdge,LastEdge;
998   Init(Path,Edge1,Edge2,Offset,FirstEdge,LastEdge,Polynomial,Tol,Conti);
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 TopoDS_Edge&     FirstEdge,
1012                              const TopoDS_Edge&     LastEdge,
1013                              const Standard_Boolean Polynomial,
1014                              const Standard_Real    Tol,
1015                              const GeomAbs_Shape    Conti)
1016 {
1017   Standard_Boolean C1Denerated = Standard_False;
1018   Standard_Boolean C2Denerated = Standard_False;
1019   myStatus = BRepOffset_Good;
1020   myShape = Path;
1021
1022   TopLoc_Location Loc;
1023   Standard_Real f[3],l[3];
1024
1025   Handle(Geom_Curve) CP = BRep_Tool::Curve(Path,Loc,f[0],l[0]);
1026   CP = new Geom_TrimmedCurve(CP,f[0], l[0]);
1027   CP->Transform(Loc.Transformation());
1028   Handle(GeomAdaptor_HCurve) HCP = new GeomAdaptor_HCurve(CP);
1029
1030   Handle(Geom_Curve) C1 = BRep_Tool::Curve(Edge1,Loc,f[1],l[1]);
1031
1032   Handle(Adaptor3d_HCurve) HEdge1;
1033   Standard_Boolean C1is3D = Standard_True;
1034   if (C1.IsNull()) {
1035     C1is3D = Standard_False;
1036     Handle(Geom2d_Curve) C12d;
1037     Handle(Geom_Surface) S1;
1038     BRep_Tool::CurveOnSurface(Edge1,C12d,S1,Loc,f[1],l[1]);
1039     S1 = Handle(Geom_Surface)::DownCast(S1->Transformed(Loc.Transformation()));
1040     C12d = new Geom2d_TrimmedCurve(C12d,f[1],l[1]);
1041     Handle(GeomAdaptor_HSurface) HS1 = new GeomAdaptor_HSurface(S1);
1042     Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C12d);
1043     Adaptor3d_CurveOnSurface Cons(HC1,HS1);
1044     HEdge1 = new Adaptor3d_HCurveOnSurface(Cons);
1045   }
1046   else {
1047     C1 = new Geom_TrimmedCurve(C1, f[1], l[1]);
1048     C1->Transform(Loc.Transformation());
1049     HEdge1 = new GeomAdaptor_HCurve(C1);
1050     GeomAdaptor_Curve AC1(C1);
1051     if ( AC1.GetType() == GeomAbs_Circle) {
1052       C1Denerated = (AC1.Circle().Radius() < Precision::Confusion());
1053     }
1054   }
1055
1056   Handle(Geom_Curve) C2 = BRep_Tool::Curve(Edge2,Loc,f[2],l[2]);
1057
1058   Handle(Adaptor3d_HCurve) HEdge2;
1059   Standard_Boolean C2is3D = Standard_True;
1060   if (C2.IsNull()) {
1061     C2is3D = Standard_False;
1062     Handle(Geom2d_Curve) C12d;
1063     Handle(Geom_Surface) S1;
1064     BRep_Tool::CurveOnSurface(Edge2,C12d,S1,Loc,f[2],l[2]);
1065     S1 = Handle(Geom_Surface)::DownCast(S1->Transformed(Loc.Transformation()));
1066     C12d = new Geom2d_TrimmedCurve(C12d,f[2],l[2]);
1067     Handle(GeomAdaptor_HSurface) HS1 = new GeomAdaptor_HSurface(S1);
1068     Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C12d);
1069     Adaptor3d_CurveOnSurface Cons(HC1,HS1);
1070     HEdge2 = new Adaptor3d_HCurveOnSurface(Cons);
1071   }
1072   else {
1073     C2 = new Geom_TrimmedCurve(C2, f[2], l[2]);
1074     C2->Transform(Loc.Transformation());
1075     HEdge2 = new GeomAdaptor_HCurve(C2);
1076     GeomAdaptor_Curve AC2(C2);
1077     if ( AC2.GetType() == GeomAbs_Circle) {
1078       C2Denerated = (AC2.Circle().Radius() < Precision::Confusion());
1079     }
1080   }
1081   
1082   // Calcul du tuyau
1083   GeomFill_Pipe Pipe(HCP, HEdge1, HEdge2, Abs(Offset));
1084   Pipe.Perform(Tol, Polynomial, Conti);
1085   Standard_Real ErrorPipe = Pipe.ErrorOnSurf();
1086
1087   Handle(Geom_Surface) S = Pipe.Surface();
1088   Standard_Boolean ExchUV = Pipe.ExchangeUV();
1089   Standard_Real f1,l1,f2,l2;
1090   S->Bounds(f1,l1,f2,l2);
1091
1092   // Perform the face
1093   Standard_Real PathTol = BRep_Tool::Tolerance(Path);
1094   Standard_Real TheTol;
1095   BRep_Builder myBuilder;
1096   myBuilder.MakeFace(myFace);
1097   TopLoc_Location Id;
1098   myBuilder.UpdateFace(myFace,S,Id,PathTol);
1099
1100   // update de Edge1. (Rem : has already a 3d curve)
1101   Standard_Real U,U1,U2;
1102   Handle(Geom2d_Curve) PC;
1103   if ( ExchUV) {
1104     PC = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1105     U1 = f1;
1106     U2 = l1;
1107     if (!C1is3D) C1 = S->VIso(f2);
1108   }
1109   else  {
1110     PC = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1111     U1 = f2;
1112     U2 = l2;
1113     if (!C1is3D) C1 = S->UIso(f1);
1114   }
1115   
1116   Handle(Geom_Curve) Dummy;
1117   if (!C1is3D)
1118     UpdateEdge(Edge1,C1,Id,BRep_Tool::Tolerance(Edge1));
1119   else if ( C1Denerated) {
1120     UpdateEdge(Edge1,Dummy,Id,BRep_Tool::Tolerance(Edge1));
1121     myBuilder.Degenerated(Edge1,Standard_True);
1122   }
1123
1124   TheTol = Max(PathTol, BRep_Tool::Tolerance(Edge1) + ErrorPipe);
1125   UpdateEdge(Edge1, PC, myFace, TheTol);
1126
1127   // mise a same range de la nouvelle pcurve.
1128   if ( !C1is3D && !C1Denerated)
1129   {
1130     myBuilder.SameRange    (Edge1,Standard_False);
1131     myBuilder.Range(Edge1,U1,U2, Standard_True);
1132   }
1133   myBuilder.Range(Edge1,myFace,U1,U2);
1134   BRepLib::SameRange(Edge1);
1135   
1136   // mise a sameparameter pour les KPart
1137   if (ErrorPipe == 0) {
1138     TheTol = Max(TheTol, Tol); 
1139     myBuilder.SameParameter(Edge1,Standard_False);
1140     BRepLib::SameParameter(Edge1, TheTol);
1141   }
1142   
1143   // Update de edge2. (Rem : has already a 3d curve)
1144   if (ExchUV) {
1145     PC = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));
1146     U1 = f1;
1147     U2 = l1;
1148     if (!C2is3D) C2 = S->VIso(l2);
1149   }
1150   else {
1151     PC = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));
1152     U1 = f2;
1153     U2 = l2;
1154     if (!C2is3D) C2 = S->UIso(l1);
1155   }
1156
1157   if (!C2is3D)
1158     UpdateEdge(Edge2,C2,Id,BRep_Tool::Tolerance(Edge2));
1159   else if ( C2Denerated) {
1160     UpdateEdge(Edge2,Dummy,Id,BRep_Tool::Tolerance(Edge2));
1161     myBuilder.Degenerated(Edge2,Standard_True);
1162   }
1163
1164   TheTol = Max(PathTol, BRep_Tool::Tolerance(Edge2) + ErrorPipe);
1165   UpdateEdge(Edge2, PC, myFace, TheTol);
1166
1167   // mise a same range de la nouvelle pcurve.
1168   myBuilder.SameRange    (Edge2,Standard_False);
1169   if ( !C2is3D && !C2Denerated)
1170     myBuilder.Range(Edge2, U1, U2, Standard_True);
1171   myBuilder.Range(Edge2,myFace,U1,U2);
1172   BRepLib::SameRange(Edge2);
1173   
1174   // mise a sameparameter pour les KPart
1175   if (ErrorPipe == 0) {
1176    TheTol = Max(TheTol, Tol); 
1177     myBuilder.SameParameter(Edge2,Standard_False);
1178     BRepLib::SameParameter(Edge2, TheTol);
1179   }
1180
1181   TopoDS_Edge Edge3, Edge4;
1182   // eval edge3
1183   TopoDS_Vertex V1f,V1l,V2f,V2l;
1184   TopExp::Vertices(Path,V1f,V1l);
1185   Standard_Boolean IsClosed = ( V1f.IsSame(V1l));
1186
1187   TopExp::Vertices(Edge1,V1f,V1l);
1188   TopExp::Vertices(Edge2,V2f,V2l);
1189
1190   Standard_Boolean StartDegenerated = (V1f.IsSame(V2f));
1191   Standard_Boolean EndDegenerated   = (V1l.IsSame(V2l));
1192
1193   Standard_Boolean E3rev = Standard_False;
1194   Standard_Boolean E4rev = Standard_False;
1195   
1196   TopoDS_Vertex VVf,VVl;
1197   if ( FirstEdge.IsNull()) {
1198     myBuilder.MakeEdge(Edge3);
1199     myBuilder.Add(Edge3,V1f.Oriented(TopAbs_FORWARD));
1200     myBuilder.Add(Edge3,V2f.Oriented(TopAbs_REVERSED));
1201   }
1202   else {
1203     TopoDS_Shape aLocalEdge = FirstEdge.Oriented(TopAbs_FORWARD);
1204     Edge3 = TopoDS::Edge(aLocalEdge);
1205 //    Edge3 = TopoDS::Edge(FirstEdge.Oriented(TopAbs_FORWARD));
1206     TopExp::Vertices(Edge3,VVf,VVl);
1207 #ifdef OCCT_DEBUG
1208     // si firstedge n est pas nul, il faut que les vertex soient partages
1209     if ( !VVf.IsSame(V1f) && !VVf.IsSame(V2f) ) {
1210       cout << "Attention Vertex non partages !!!!!!" << endl;
1211     }    
1212 #endif
1213     if ( !VVf.IsSame(V1f) && !VVf.IsSame(V2f) ) {
1214       // On fait vraisemblablement des conneries !!
1215       // On cree un autre edge, on appelle le Sewing apres.
1216       myBuilder.MakeEdge(Edge3);
1217       myBuilder.Add(Edge3,V1f.Oriented(TopAbs_FORWARD));
1218       myBuilder.Add(Edge3,V2f.Oriented(TopAbs_REVERSED));
1219     }
1220     else if ( !VVf.IsSame(V1f)) {
1221       Edge3.Reverse();
1222       E3rev = Standard_True;
1223     }
1224   }
1225
1226   if ( IsClosed)
1227     Edge4 = Edge3;
1228
1229   Standard_Real TolApp = Precision::Approximation();
1230
1231   Handle(Geom2d_Line) L1,L2;
1232   if ( IsClosed) {
1233     if ( ExchUV) {
1234       // rem : si ExchUv, il faut  reverser le Wire. 
1235       // donc l'edge Forward dans la face sera E4 : d'ou L1 et L2
1236       L2 = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1237       L1 = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));
1238       U1 = f2;
1239       U2 = l2;
1240     }
1241     else {
1242       L1 = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1243       L2 = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));
1244       U1 = f1;
1245       U2 = l1;
1246     }
1247     if ( E3rev) {
1248       L1->Reverse(); L2->Reverse();
1249       U  = -U1;
1250       U1 = -U2;
1251       U2 =  U;
1252     }
1253     UpdateEdge(Edge3, L1, L2, myFace,PathTol);
1254     myBuilder.Range(Edge3,myFace,U1,U2);
1255     if (StartDegenerated) 
1256       myBuilder.Degenerated(Edge3,Standard_True);
1257     else if (FirstEdge.IsNull()) // then the 3d curve has not been yet computed
1258       ComputeCurve3d(Edge3,L1,S,Id,TolApp);
1259   }
1260   else {
1261     if ( LastEdge.IsNull()) {
1262       myBuilder.MakeEdge(Edge4);
1263       myBuilder.Add(Edge4,V1l.Oriented(TopAbs_FORWARD));
1264       myBuilder.Add(Edge4,V2l.Oriented(TopAbs_REVERSED));
1265     }
1266     else {
1267       TopoDS_Shape aLocalEdge = LastEdge.Oriented(TopAbs_FORWARD);
1268       Edge4 = TopoDS::Edge(aLocalEdge);
1269 //      Edge4 = TopoDS::Edge(LastEdge.Oriented(TopAbs_FORWARD));
1270       TopExp::Vertices(Edge4,VVf,VVl);
1271 #ifdef OCCT_DEBUG
1272       // si lastedge n est pas nul, il faut que les vertex soient partages
1273       if ( !VVf.IsSame(V1l) && !VVf.IsSame(V2l) ) {
1274         cout << "Attention Vertex non partages !!!!!!" << endl;
1275       }    
1276 #endif
1277       if ( !VVf.IsSame(V1l) && !VVf.IsSame(V2l) ) {
1278         // On fait vraisemblablement des conneries !!
1279         // On cree un autre edge, on appelle le Sewing apres.
1280         myBuilder.MakeEdge(Edge4);
1281         myBuilder.Add(Edge4,V1l.Oriented(TopAbs_FORWARD));
1282         myBuilder.Add(Edge4,V2l.Oriented(TopAbs_REVERSED));
1283       }
1284       else if ( !VVf.IsSame(V1l)) {
1285         Edge4.Reverse();
1286         E4rev = Standard_True;
1287       }
1288     }
1289
1290     if (ExchUV) {
1291       L1 = new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1));
1292       U1 = f2;
1293       U2 = l2;
1294     }
1295     else {
1296       L1 = new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0));
1297       U1 = f1;
1298       U2 = l1;
1299     }
1300     if ( E3rev) {
1301       L1->Reverse();
1302       U  = -U1;
1303       U1 = -U2;
1304       U2 =  U;
1305     }
1306     UpdateEdge(Edge3,L1,myFace,PathTol);
1307     myBuilder.Range(Edge3,myFace,U1,U2);
1308     if (StartDegenerated) 
1309       myBuilder.Degenerated(Edge3,Standard_True);
1310     else if (FirstEdge.IsNull()) // then the 3d curve has not been yet computed
1311       ComputeCurve3d(Edge3,L1,S,Id,TolApp);
1312
1313     if (ExchUV) {
1314       L2 = new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1));    
1315       U1 = f2;
1316       U2 = l2;
1317     }
1318     else {
1319       L2 = new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0));    
1320       U1 = f1;
1321       U2 = l1;
1322     }
1323     if ( E4rev) {
1324       L2->Reverse();
1325       U  = -U1;
1326       U1 = -U2;
1327       U2 =  U;
1328     }
1329     UpdateEdge(Edge4,L2 ,myFace,PathTol);
1330     myBuilder.Range(Edge4,myFace,U1,U2);   
1331     if (EndDegenerated) 
1332       myBuilder.Degenerated(Edge4,Standard_True);
1333     else if (LastEdge.IsNull()) // then the 3d curve has not been yet computed
1334       ComputeCurve3d(Edge4,L2,S,Id,TolApp);
1335   }
1336   
1337   // SameParameter ??
1338   if ( !FirstEdge.IsNull() && !StartDegenerated) {
1339     BRepLib::BuildCurve3d  (Edge3,PathTol);
1340     myBuilder.SameRange    (Edge3,Standard_False);
1341     myBuilder.SameParameter(Edge3,Standard_False);
1342     BRepLib::SameParameter (Edge3, Tol);
1343   }
1344   if ( !LastEdge.IsNull() && !EndDegenerated) {
1345     BRepLib::BuildCurve3d  (Edge4,PathTol);
1346     myBuilder.SameRange    (Edge4,Standard_False);
1347     myBuilder.SameParameter(Edge4,Standard_False);
1348     BRepLib::SameParameter (Edge4, Tol);
1349   }
1350
1351   TopoDS_Wire W;
1352   myBuilder.MakeWire(W);
1353   
1354   myBuilder.Add(W, Edge1.Oriented(TopAbs_REVERSED));
1355   myBuilder.Add(W, Edge2.Oriented(TopAbs_FORWARD));
1356   myBuilder.Add(W, Edge4.Reversed());
1357   myBuilder.Add(W, Edge3);
1358
1359   if (ExchUV) { 
1360     W.Reverse();
1361   }    
1362
1363   myBuilder.Add(myFace, W);
1364   if (ExchUV) myFace.Reverse();
1365
1366   BRepTools::Update(myFace);
1367
1368   if ( Edge1.Orientation() == TopAbs_REVERSED)
1369     myFace.Reverse();
1370
1371 }
1372
1373
1374 //=======================================================================
1375 //function : Init
1376 //purpose  : 
1377 //=======================================================================
1378
1379 void BRepOffset_Offset::Init(const TopoDS_Vertex&        Vertex,
1380                              const TopTools_ListOfShape& LEdge,
1381                              const Standard_Real         Offset,
1382                              const Standard_Boolean      Polynomial,
1383                              const Standard_Real         TolApp,
1384                              const GeomAbs_Shape         Conti)
1385 {
1386   myStatus = BRepOffset_Good;
1387   myShape = Vertex;
1388
1389   // evaluate the Ax3 of the Sphere
1390   // find 3 different vertices in LEdge
1391   TopTools_ListIteratorOfListOfShape it;
1392   gp_Pnt P, P1, P2, P3;
1393   TopoDS_Vertex V1, V2, V3, V4;
1394
1395
1396 #ifdef OCCT_DEBUG
1397   char* name = new char[100];
1398   if (Affich) {
1399     NbOFFSET++;
1400     
1401     sprintf(name,"VOnSph_%d",NbOFFSET);
1402 #ifdef DRAW
1403     DBRep::Set(name, Vertex);
1404 #endif
1405     Standard_Integer NbEdges = 1;
1406     for (it.Initialize(LEdge); it.More(); it.Next()) {
1407       sprintf(name,"EOnSph_%d_%d",NbOFFSET,NbEdges++);
1408 #ifdef DRAW
1409       const TopoDS_Shape& CurE = it.Value();
1410       DBRep::Set(name, CurE);
1411 #endif
1412     }
1413
1414   }
1415 #endif
1416
1417   gp_Pnt Origin = BRep_Tool::Pnt(Vertex);
1418
1419   //// Find the axis of the sphere to exclude
1420   //// degenerated and seam edges from the face under construction
1421   BRepLib_MakeWire MW;
1422   MW.Add(LEdge);
1423   TopoDS_Wire theWire = MW.Wire();
1424
1425   ShapeFix_Shape Fixer(theWire);
1426   Fixer.Perform();
1427   theWire = TopoDS::Wire(Fixer.Shape());
1428
1429   GProp_GProps GlobalProps;
1430   BRepGProp::LinearProperties(theWire, GlobalProps);
1431   gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
1432   gp_Vec Xdir(BaryCenter, Origin);
1433
1434   gp_Pnt FarestCorner = GetFarestCorner(theWire);
1435   gp_Pln thePlane = gce_MakePln(Origin, BaryCenter, FarestCorner);
1436   gp_Dir Vdir = thePlane.Axis().Direction();
1437
1438   gp_Ax3 Axis(Origin, Vdir, Xdir);
1439   
1440   Handle(Geom_Surface) S 
1441     = new Geom_SphericalSurface( Axis, Abs(Offset));
1442
1443   Standard_Real f, l, Tol = BRep_Tool::Tolerance(Vertex);
1444   
1445   TopLoc_Location Loc;
1446   BRep_Builder myBuilder;
1447   myBuilder.MakeFace(myFace);
1448   Handle(Geom_Surface) SS = S;
1449
1450   // En polynomial, calcul de la surface par F(u,v).
1451   // Pas de changement de parametre, donc ProjLib sur la Sphere
1452   // reste OK.
1453   if (Polynomial) {
1454     GeomConvert_ApproxSurface Approx(S,TolApp,Conti,Conti,10,10,10,1);
1455     if (Approx.IsDone()) {
1456       SS = Approx.Surface();
1457     }
1458   }
1459
1460   myBuilder.UpdateFace(myFace, SS, Loc, Tol);
1461   
1462   TopoDS_Wire W;
1463   myBuilder.MakeWire(W);
1464   
1465 #ifdef DRAW
1466   // POP pour NT
1467   //  char name[100];
1468   if (Affich) {
1469     sprintf(name,"SPHERE_%d",NbOFFSET);
1470     DrawTrSurf::Set(name, S);
1471   }
1472   Standard_Integer CO = 1;
1473 #endif
1474
1475   for ( it.Initialize(LEdge); it.More(); it.Next()) {
1476     TopoDS_Edge E = TopoDS::Edge(it.Value());
1477
1478     Handle(Geom_Curve) C = BRep_Tool::Curve(E,Loc,f,l);
1479     if ( C.IsNull()) {
1480       BRepLib::BuildCurve3d(E,BRep_Tool::Tolerance(E));
1481       C = BRep_Tool::Curve(E,Loc,f,l);
1482     }
1483     C = new Geom_TrimmedCurve(C, f, l);
1484     C->Transform(Loc.Transformation());
1485
1486 #ifdef DRAW
1487     if ( Affich) {
1488       sprintf(name,"CURVE_%d_%d",NbOFFSET,CO);
1489       DrawTrSurf::Set(name, C);
1490       CO++;
1491     }
1492 #endif
1493
1494     Handle(Geom2d_Curve) PCurve = GeomProjLib::Curve2d(C, S);
1495     // check if the first point of PCurve in is the canonical boundaries 
1496     // of the sphere. Else move it.
1497     // the transformation is : U` = U + PI + 2 k  PI
1498     //                         V` = +/- PI + 2 k` PI
1499     gp_Pnt2d P2d = PCurve->Value(f);
1500     Standard_Boolean IsToAdjust = Standard_False;
1501     if ( P2d.Y() < -M_PI/2.) {
1502       IsToAdjust = Standard_True;
1503       PCurve->Mirror(gp_Ax2d(gp_Pnt2d(0.,-M_PI/2.),gp::DX2d()));
1504     }
1505     else if ( P2d.Y() > M_PI/2.) {
1506       IsToAdjust = Standard_True;
1507       PCurve->Mirror(gp_Ax2d(gp_Pnt2d(0., M_PI/2.),gp::DX2d()));
1508     }
1509     if ( IsToAdjust) {
1510       // set the u firstpoint in [0,2*pi]
1511       gp_Vec2d Tr( M_PI, 0.);
1512       if ( P2d.X() > M_PI) Tr.Reverse();
1513       PCurve->Translate(Tr);
1514     }
1515
1516     UpdateEdge(E, PCurve, myFace, Tol);
1517     myBuilder.Range(E, myFace, f, l);
1518     myBuilder.Add(W, E);
1519   }
1520   if ( Offset < 0.) {
1521     myBuilder.Add(myFace, W.Oriented(TopAbs_REVERSED));
1522     myFace.Reverse();
1523   }
1524   else {
1525     myBuilder.Add(myFace, W);
1526   }
1527
1528   BRepTools::Update(myFace);
1529 }
1530
1531
1532 //=======================================================================
1533 //function : Init
1534 //purpose  : 
1535 //=======================================================================
1536
1537 void BRepOffset_Offset::Init(const TopoDS_Edge&  Edge,
1538                              const Standard_Real Offset)
1539 {
1540   myShape   = Edge;
1541   Standard_Real myOffset = Abs(Offset);
1542
1543   Standard_Real f,l;
1544   TopLoc_Location Loc;
1545
1546   Handle(Geom_Curve) CP = BRep_Tool::Curve(Edge,Loc,f,l);
1547   CP = new Geom_TrimmedCurve(CP,f,l);
1548   CP->Transform(Loc.Transformation());
1549
1550   GeomFill_Pipe Pipe(CP,myOffset);
1551   Pipe.Perform();
1552
1553   BRepLib_MakeFace MF(Pipe.Surface(), Precision::Confusion());
1554   myFace = MF.Face();
1555
1556   if ( Offset < 0.) myFace.Reverse();
1557 }
1558
1559
1560 //=======================================================================
1561 //function : Face
1562 //purpose  : 
1563 //=======================================================================
1564
1565 const TopoDS_Face& BRepOffset_Offset::Face() const 
1566 {
1567   return myFace;
1568 }
1569
1570
1571 //=======================================================================
1572 //function : Generated
1573 //purpose  : 
1574 //=======================================================================
1575
1576 TopoDS_Shape BRepOffset_Offset::Generated(const TopoDS_Shape& Shape) const 
1577 {
1578   TopoDS_Shape aShape;
1579
1580   switch ( myShape.ShapeType()) {
1581
1582   case TopAbs_FACE: 
1583     {
1584       TopExp_Explorer exp (myShape.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1585       TopExp_Explorer expo(myFace .Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1586       for ( ; exp.More() && expo.More(); exp.Next(), expo.Next()) {
1587         if ( Shape.IsSame(exp.Current())) {
1588           if ( myShape.Orientation() == TopAbs_REVERSED) 
1589             aShape = expo.Current().Reversed();
1590           else
1591             aShape = expo.Current();
1592         }
1593       }
1594     }
1595     break;
1596
1597   case TopAbs_EDGE:
1598     // have generate a pipe.
1599     {
1600       TopoDS_Vertex V1, V2;
1601       TopExp::Vertices(TopoDS::Edge(myShape), V1, V2);
1602       
1603       TopExp_Explorer expf(myFace .Oriented(TopAbs_FORWARD), TopAbs_WIRE);
1604       TopExp_Explorer expo(expf.Current().Oriented(TopAbs_FORWARD), 
1605                            TopAbs_EDGE);
1606       expo.Next(); 
1607       expo.Next();
1608       
1609       if ( V2.IsSame(Shape)) {
1610         if ( expf.Current().Orientation() == TopAbs_REVERSED) 
1611           aShape = expo.Current().Reversed();
1612         else
1613           aShape = expo.Current();
1614       }
1615       else {
1616         expo.Next();
1617         if ( expf.Current().Orientation() == TopAbs_REVERSED) 
1618           aShape = expo.Current().Reversed();
1619         else
1620           aShape = expo.Current();
1621       }
1622       if ( myFace.Orientation() == TopAbs_REVERSED)
1623         aShape.Reverse();
1624     }
1625     break;
1626   default:
1627     break;
1628   }
1629
1630   return aShape;
1631 }
1632
1633
1634 //=======================================================================
1635 //function : Status
1636 //purpose  : 
1637 //=======================================================================
1638
1639 BRepOffset_Status BRepOffset_Offset::Status() const 
1640 {
1641   return myStatus;
1642 }
1643
1644
1645