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