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