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