01fd76e0395738a405a1e95c3c0926ce957b31b1
[occt.git] / src / GeomToIGES / GeomToIGES_GeomCurve.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 // modif du 04/03/96 mjm
15 // modif dans IGESConvGeom_GeomBuilder
16 //#53 rln 24.12.98 CCI60005
17 //#59 rln 29.12.98 PRO17015
18 //%11 pdn 12.01.99 CTS22023: writing offset curves and detecting planar curves
19 //%12 pdn 13.01.99: CTS22023: cutting bspline curves (for Euclid3)
20 //:l7 abv 13.01.99: CTS22021: using QuasiAngular parametrisation for circles (more precise)
21 //:l5 abv 14.01.99: CTS22022-1: protection against exceptions in Segment()
22 //:q3 abv 17.03.99: PRO17828: using GeomConvert_ApproxCurve for converting circle to bspline
23
24 #include <BSplCLib.hxx>
25 #include <Geom_BezierCurve.hxx>
26 #include <Geom_BoundedCurve.hxx>
27 #include <Geom_BSplineCurve.hxx>
28 #include <Geom_Circle.hxx>
29 #include <Geom_Conic.hxx>
30 #include <Geom_Curve.hxx>
31 #include <Geom_Ellipse.hxx>
32 #include <Geom_Hyperbola.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_OffsetCurve.hxx>
35 #include <Geom_Parabola.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <GeomConvert.hxx>
38 #include <GeomConvert_ApproxCurve.hxx>
39 #include <GeomToIGES_GeomCurve.hxx>
40 #include <GeomToIGES_GeomEntity.hxx>
41 #include <gp.hxx>
42 #include <gp_Ax2.hxx>
43 #include <gp_Ax3.hxx>
44 #include <gp_Ax22d.hxx>
45 #include <gp_Circ.hxx>
46 #include <gp_Dir.hxx>
47 #include <gp_Elips.hxx>
48 #include <gp_Elips2d.hxx>
49 #include <gp_Hypr.hxx>
50 #include <gp_Hypr2d.hxx>
51 #include <gp_Parab.hxx>
52 #include <gp_Parab2d.hxx>
53 #include <gp_Pnt.hxx>
54 #include <gp_XY.hxx>
55 #include <gp_XYZ.hxx>
56 #include <IGESConvGeom_GeomBuilder.hxx>
57 #include <IGESData_IGESEntity.hxx>
58 #include <IGESData_ToolLocation.hxx>
59 #include <IGESGeom_BSplineCurve.hxx>
60 #include <IGESGeom_CircularArc.hxx>
61 #include <IGESGeom_CompositeCurve.hxx>
62 #include <IGESGeom_ConicArc.hxx>
63 #include <IGESGeom_CopiousData.hxx>
64 #include <IGESGeom_CurveOnSurface.hxx>
65 #include <IGESGeom_Line.hxx>
66 #include <IGESGeom_OffsetCurve.hxx>
67 #include <IGESGeom_Point.hxx>
68 #include <IGESGeom_TransformationMatrix.hxx>
69 #include <Interface_Macros.hxx>
70 #include <Interface_Static.hxx>
71 #include <Precision.hxx>
72 #include <ShapeCustom_BSplineRestriction.hxx>
73 #include <Standard_ErrorHandler.hxx>
74 #include <Standard_Failure.hxx>
75 #include <TColgp_Array1OfPnt.hxx>
76 #include <TColgp_HArray1OfXYZ.hxx>
77 #include <TColStd_Array1OfReal.hxx>
78 #include <TColStd_HArray1OfReal.hxx>
79
80 // Pour toutes les courbes infinies soit 
81 // Udeb <= -Precision::Infinite() et/ou Ufin >= Precision::Infinite()
82 // on choisit arbitrairement de les construire entre 
83 // Udeb = -Precision::Infinite() et Ufin = Precision::Infinite()
84 //=============================================================================
85 // GeomToIGES_GeomCurve
86 //=============================================================================
87 GeomToIGES_GeomCurve::GeomToIGES_GeomCurve()
88 :GeomToIGES_GeomEntity()
89 {
90 }
91
92
93 //=============================================================================
94 // GeomToIGES_GeomCurve
95 //=============================================================================
96
97 GeomToIGES_GeomCurve::GeomToIGES_GeomCurve
98 (const GeomToIGES_GeomEntity& GE)
99 :GeomToIGES_GeomEntity(GE)
100 {
101 }
102
103
104 //=============================================================================
105 // Transfer des Entites Curve de Geom vers IGES
106 // TransferCurve
107 //=============================================================================
108
109 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
110 (const Handle(Geom_Curve)& start, const Standard_Real Udeb, 
111  const Standard_Real Ufin)
112 {
113   Handle(IGESData_IGESEntity) res;
114   if (start.IsNull()) {
115     return res;
116   }
117
118   if (start->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
119     DeclareAndCast(Geom_BoundedCurve, Bounded, start);
120     res = TransferCurve(Bounded, Udeb, Ufin);
121   }
122   else if (start->IsKind(STANDARD_TYPE(Geom_Conic))) {
123     DeclareAndCast(Geom_Conic, Conic, start);
124     res = TransferCurve(Conic, Udeb, Ufin);
125   }
126   else if ( start->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
127     DeclareAndCast(Geom_OffsetCurve, OffsetC, start);
128     res = TransferCurve(OffsetC, Udeb, Ufin);
129   }
130   else if ( start->IsKind(STANDARD_TYPE(Geom_Line))) {
131     DeclareAndCast(Geom_Line, Line, start);
132     res = TransferCurve(Line, Udeb, Ufin);
133   }  
134   return res;
135 }
136  
137
138
139 //=============================================================================
140 // Transfer des Entites BoundedCurve de Geom vers IGES
141 // TransferCurve
142 //=============================================================================
143
144 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
145 (const Handle(Geom_BoundedCurve)& start, const Standard_Real Udeb, 
146  const Standard_Real Ufin)
147 {
148   Handle(IGESData_IGESEntity) res;
149   if (start.IsNull()) {
150     return res;
151   }
152
153   if (start->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
154     DeclareAndCast(Geom_BSplineCurve, Bspline, start);
155     res = TransferCurve(Bspline, Udeb, Ufin);
156   }
157   else if (start->IsKind(STANDARD_TYPE(Geom_BezierCurve))) {
158     DeclareAndCast(Geom_BezierCurve, Bezier, start);
159     res = TransferCurve(Bezier, Udeb, Ufin);
160   }
161   else if ( start->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
162     DeclareAndCast(Geom_TrimmedCurve, Trimmed, start);
163     res = TransferCurve(Trimmed, Udeb, Ufin);
164   }
165   
166   return res;
167 }
168  
169 //%11 pdn 12.01.98
170 //=============================================================================
171 // Detects if curve lies in some plane and returns normal
172 // IsPlanar
173 //=============================================================================
174 static gp_XYZ GetAnyNormal ( gp_XYZ orig )
175 {
176   gp_XYZ Norm;
177   if ( Abs ( orig.Z() ) < Precision::Confusion() )
178     Norm.SetCoord ( 0, 0, 1 );
179   else {
180     Norm.SetCoord ( orig.Z(), 0, -orig.X() );
181     Standard_Real nrm = Norm.Modulus();
182     if ( nrm < Precision::Confusion() ) Norm.SetCoord ( 0, 0, 1 );
183     else Norm = Norm / nrm;
184   }
185   return Norm;
186 }
187
188 //%11 pdn 12.01.98
189 //=============================================================================
190 // Detects if curve lies in some plane and returns normal
191 // IsPlanar
192 //=============================================================================
193 static Standard_Boolean ArePolesPlanar (const TColgp_Array1OfPnt& Poles,
194                                         gp_XYZ& Normal)
195 {
196   if(Poles.Length()<3) {
197     Normal = GetAnyNormal(Poles(1).XYZ()-Poles(2).XYZ());
198     return Standard_True;
199   }
200   
201   Normal = Poles(Poles.Length()).XYZ() ^ Poles(1).XYZ();
202   Standard_Integer i; // svv Jan 10 2000 : porting on DEC
203   for ( i = 1; i < Poles.Length(); i++) 
204     Normal += Poles ( i ).XYZ() ^ Poles ( i + 1 ).XYZ();
205
206   Standard_Real tol = Precision::Confusion();
207   Standard_Real nrm = Normal.Modulus();
208   if ( nrm < tol ) {
209     Normal.SetCoord ( 0, 0, 1 );
210     return Standard_False;
211   }
212   Normal = Normal / nrm;
213
214   Standard_Real scl = Poles(1).XYZ() * Normal;
215   for ( i = 2; i <= Poles.Length(); i++ )
216     if ( Abs ( Poles(i).XYZ() * Normal - scl ) > tol ) return Standard_False;
217   return Standard_True;
218 }
219
220 //%11 pdn 12.01.98
221 //=============================================================================
222 // Detects if curve lies in some plane and returns normal
223 // IsPlanar
224 //=============================================================================
225 static Standard_Boolean IsPlanar(const Handle(Geom_Curve)& curve,
226                                  gp_XYZ& Normal)
227 {
228   Normal.SetCoord(0,0,0);
229   if ( curve->IsKind(STANDARD_TYPE(Geom_Line))) {
230     DeclareAndCast(Geom_Line, Line, curve);
231     Normal = GetAnyNormal(Line->Position().Direction().XYZ());
232     return Standard_True;
233   }
234   if ( curve->IsKind(STANDARD_TYPE(Geom_Conic))) {
235     DeclareAndCast(Geom_Conic, Conic, curve);
236     Normal = Conic->Axis().Direction().XYZ();
237     return Standard_True;
238   }
239   if ( curve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
240     DeclareAndCast(Geom_TrimmedCurve, Trimmed, curve);
241     return IsPlanar(Trimmed->BasisCurve(),Normal);
242   }
243   if ( curve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))) {
244     DeclareAndCast(Geom_OffsetCurve, OffsetC, curve);
245     return IsPlanar(OffsetC->BasisCurve(),Normal);
246   }
247   if ( curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
248     DeclareAndCast(Geom_BSplineCurve, BSpline, curve);
249     TColgp_Array1OfPnt Poles(1,BSpline->NbPoles());
250     BSpline->Poles(Poles);
251     return ArePolesPlanar(Poles,Normal);
252   }
253   if ( curve->IsKind(STANDARD_TYPE(Geom_BezierCurve)))  {
254     DeclareAndCast(Geom_BezierCurve, Bezier, curve);
255     TColgp_Array1OfPnt Poles(1,Bezier->NbPoles());
256     Bezier->Poles(Poles);
257     return ArePolesPlanar(Poles,Normal);
258   }
259   return Standard_False;
260 }
261
262 //=============================================================================
263 // Transfer des Entites BSplineCurve de Geom vers IGES
264 // TransferCurve
265 //=============================================================================
266
267 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
268 (const Handle(Geom_BSplineCurve)& start, const Standard_Real Udeb, 
269  const Standard_Real Ufin)
270 {
271   Handle(IGESData_IGESEntity) res;
272   if (start.IsNull()) {
273     return res;
274   }
275
276   Handle(Geom_BSplineCurve) mycurve;
277   Standard_Boolean IPlan  = Standard_False;
278   gp_XYZ Norm = gp_XYZ(0.,0.,1.);
279
280 // Si la courbe est periodique, on passe par une fonction pour recuperer tous
281 // les parametres necessaires a l`ecriture IGES.
282
283   Standard_Boolean IPerio  = start->IsPeriodic();
284  
285   if (IPerio) {
286     mycurve = Handle(Geom_BSplineCurve)::DownCast(start->Copy());
287     mycurve->SetNotPeriodic();
288   }
289   else {
290     mycurve = start;
291   }
292
293   Standard_Real Umin = Udeb;
294   Standard_Real Umax = Ufin;
295   if (Precision::IsNegativeInfinite(Udeb)) Umin = -Precision::Infinite();
296   if (Precision::IsPositiveInfinite(Ufin)) Umax = Precision::Infinite();
297
298   //%12 pdn: cut curve for E3
299   Standard_Real First = mycurve->FirstParameter();
300   Standard_Real Last = mycurve->LastParameter();
301   //:l5 abv 14 Jan 99: protect against exceptions in Segment()
302   if ( Umin - First < Precision::PConfusion() ) Umin = First;
303   if ( Last - Umax  < Precision::PConfusion() ) Umax = Last;
304   if ( Umin - First > Precision::PConfusion() || Last - Umax > Precision::PConfusion() ) {
305     try {
306       OCC_CATCH_SIGNALS
307       Handle(Geom_BSplineCurve) bspl = Handle(Geom_BSplineCurve)::DownCast ( mycurve->Copy() ); 
308       if ( ! bspl.IsNull() ) {
309         if (Abs(Umax-Umin) > Precision::PConfusion())
310           bspl->Segment ( Umin, Umax );
311         mycurve = bspl;
312       }
313     }
314     catch ( Standard_Failure const& anException) {
315 #ifdef OCCT_DEBUG
316       std::cout << "Warning: GeomToIGES_GeomCurve: can't trim bspline" << std::endl;
317       std::cout << "Warning: Exception in Segment(): " ;
318       anException.Print(std::cout);
319 #endif
320       (void)anException;
321     }
322   }
323
324   Standard_Boolean IClos   = mycurve->IsClosed();
325 //  Standard_Boolean IRatio  = mycurve->IsRational();
326   Standard_Boolean IPolyn  = !(mycurve->IsRational());
327   //Standard_Boolean IPerio  = mycurve->IsPeriodic();
328   Standard_Integer Deg     = mycurve->Degree();
329   Standard_Integer Nbpoles = mycurve->NbPoles();
330 //  Standard_Integer Nbknots = mycurve->NbKnots();
331   Standard_Integer Index = Nbpoles -1;
332
333
334 // Sequence des Knots de [-Deg, Index+1] dans IGESGeom.
335 // et de [1, Nbpoles+Deg+1] dans Geom
336   Standard_Integer Knotindex;
337   Standard_Real rtampon;
338   TColStd_Array1OfReal K(1, Nbpoles+Deg+1);
339   mycurve->KnotSequence(K);
340   Standard_Integer itampon = -Deg;
341   Handle(TColStd_HArray1OfReal) Knots = new TColStd_HArray1OfReal(-Deg,Index+1);
342   for ( Knotindex=K.Lower(); Knotindex<=K.Upper(); Knotindex++) { 
343     rtampon = K.Value(Knotindex);
344     Knots->SetValue(itampon, rtampon);
345     itampon++;
346   }
347
348
349 // Tableau Weights de [0,Index]
350   TColStd_Array1OfReal W(1, Nbpoles);
351   mycurve->Weights(W);
352   itampon = 0;
353   Handle(TColStd_HArray1OfReal) Weights = new TColStd_HArray1OfReal(0,Index);
354   for ( Knotindex=W.Lower(); Knotindex<=W.Upper(); Knotindex++) { 
355     rtampon = W.Value(Knotindex);
356     Weights->SetValue(itampon, rtampon);
357     itampon++;
358   }
359
360
361 // Tableau Poles de [0,Index]
362   TColgp_Array1OfPnt P(1, Nbpoles);
363   mycurve->Poles(P);
364   Standard_Integer Poleindex;
365   itampon = 0;
366   Standard_Real Xpt, Ypt, Zpt;
367   Handle(TColgp_HArray1OfXYZ) Poles = new TColgp_HArray1OfXYZ(0,Index);
368   for ( Poleindex=P.Lower(); Poleindex<=P.Upper(); Poleindex++) { 
369     gp_Pnt ptampon = P.Value(Poleindex);
370     ptampon.Coord(Xpt, Ypt, Zpt);
371     gp_XYZ xyztampon = gp_XYZ (Xpt/GetUnit(), Ypt/GetUnit(), Zpt/GetUnit());
372     Poles->SetValue(itampon, xyztampon);
373     itampon++;
374   }
375
376   // modif mjm du 9/10/97 : mise en place d'une protection.
377 //%12  Standard_Real First = mycurve->FirstParameter();
378 //%12  Standard_Real Last = mycurve->LastParameter();
379 //:l5  if (First >  Umin) Umin = First;
380 //:l5  if (Last  <  Umax) Umax = Last;
381   Handle(IGESGeom_BSplineCurve) BSplineC = new IGESGeom_BSplineCurve; 
382   //%11 pdn 13.01.98 computing planar flag and normal
383   IPlan = IsPlanar(start,Norm);
384   if ( Norm.Z() <0 ) Norm.Reverse();
385   BSplineC->Init
386     (Index, Deg, IPlan, IClos, IPolyn, IPerio, Knots, Weights, Poles, 
387      Umin, Umax, Norm);
388   
389   res = BSplineC;
390   return res;
391 }
392  
393
394 //=============================================================================
395 // Transfer des Entites BezierCurve de Geom vers IGES
396 // TransferCurve
397 //=============================================================================
398
399 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
400 (const Handle(Geom_BezierCurve)& start, const Standard_Real Udeb, 
401  const Standard_Real Ufin)
402 {
403   Handle(IGESData_IGESEntity) res;
404   if (start.IsNull()) {
405     return res;
406   }
407
408   Handle(Geom_TrimmedCurve) mycurve3d = 
409           new Geom_TrimmedCurve(start, Udeb, Ufin);
410   Handle(Geom_BSplineCurve) Bspline = GeomConvert::CurveToBSplineCurve(mycurve3d,
411     Convert_RationalC1);//#28 rln 19.10.98 UKI60155
412   Standard_Real First = Bspline->FirstParameter();
413   Standard_Real Last  = Bspline->LastParameter();
414   res = TransferCurve(Bspline, First, Last);
415   return res;
416 }
417  
418
419 //=============================================================================
420 // Transfer des Entites TrimmedCurve de Geom vers IGES
421 // TransferCurve
422 //=============================================================================
423
424 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
425 (const Handle(Geom_TrimmedCurve)& start, const Standard_Real Udeb, 
426  const Standard_Real Ufin)
427 {
428   Handle(IGESData_IGESEntity) res;
429   if (start.IsNull()) {
430     return res;
431   }
432
433   Handle(Geom_Curve) st = start->BasisCurve();
434   if (st->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { 
435     DeclareAndCast(Geom_TrimmedCurve, Trimmed, st);
436     Handle(Geom_Curve) st1 = Trimmed->BasisCurve();
437     res = TransferCurve(st1, Udeb, Ufin);
438   }
439   
440   res = TransferCurve(st, Udeb, Ufin);
441   return res;
442 }
443  
444
445
446 //=============================================================================
447 // Transfer des Entites Conic de Geom vers IGES
448 // TransferCurve
449 //=============================================================================
450
451 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
452 (const Handle(Geom_Conic)& start, const Standard_Real Udeb,
453  const Standard_Real Ufin)
454 {
455   Handle(IGESData_IGESEntity) res;
456   if (start.IsNull()) {
457     return res;
458   }
459
460   // conic curve : Ellipse, Circle, Hyperbola, Parabola.
461   // All the conics are planar curves. An axis placement (two axis)
462   // defines the local coordinate system of the conic.
463   // The Location point, the XDirection and the YDirection of this
464   // axis placement define the plane of the conic. 
465   // The XDirection defines the origin of the curve's parametrization.
466   // The Direction (main direction) of the axis placement is normal
467   // to the plane of the conic.
468
469   if (start->IsKind(STANDARD_TYPE(Geom_Circle))) {
470     DeclareAndCast(Geom_Circle, Circle, start);
471     res = TransferCurve(Circle, Udeb, Ufin);
472   }
473   else if (start->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
474     DeclareAndCast(Geom_Ellipse, Ellipse, start);
475     res = TransferCurve(Ellipse, Udeb, Ufin);
476   }
477   else if ( start->IsKind(STANDARD_TYPE(Geom_Hyperbola))) {
478     DeclareAndCast(Geom_Hyperbola, Hyperbola, start);
479     res = TransferCurve(Hyperbola, Udeb, Ufin);
480   }
481   else if ( start->IsKind(STANDARD_TYPE(Geom_Parabola))) {
482     DeclareAndCast(Geom_Parabola, Parabola, start);
483     res = TransferCurve(Parabola, Udeb, Ufin);
484   }
485   
486   return res;
487 }
488  
489
490 //=============================================================================
491 // Transfer des Entites Circle de Geom vers IGES
492 // TransferCurve
493 //=============================================================================
494
495 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
496 (const Handle(Geom_Circle)& start , const Standard_Real Udeb, 
497  const Standard_Real Ufin)
498 {
499
500   Handle(IGESData_IGESEntity) res;
501   if (start.IsNull()) {
502     return res;
503   }
504   Handle(IGESGeom_CircularArc) Circle = new IGESGeom_CircularArc;;
505   IGESConvGeom_GeomBuilder Build;
506   
507   Standard_Real U1 = Udeb;
508   Standard_Real U2 = Ufin;
509   if (Abs(Udeb) <= gp::Resolution()) U1 = 0.0;
510   
511 // creation du "CircularArc" (#100)
512 // --------------------------------
513   Standard_Real xloc,yloc,zloc;
514   start->Circ().Location().Coord(xloc,yloc,zloc);
515   gp_Pnt Loc;
516   Loc.SetCoord(xloc,yloc,zloc);
517   gp_Ax3 Pos = gp_Ax3(start->Circ().Position());
518 // unusable  Standard_Boolean IsDirect = Pos.Direct();
519   Pos.SetLocation(Loc);
520   Build.SetPosition(Pos);
521
522   Standard_Real Xc, Yc, Zc;
523   Standard_Real Xs, Ys, Zs;
524   Standard_Real Xe, Ye, Ze;
525   //gka BUG 6542 1.09.04 BSpline curve was written in the IGES instead circle.
526   gp_Pnt pfirst,plast;
527   start->D0(U1,pfirst);
528   if(Abs (Ufin - Udeb - 2 * M_PI) <= Precision::PConfusion())
529     plast = pfirst;
530   else
531     start->D0(U2,plast);
532   //
533   Build.EvalXYZ(((start->Circ()).Location()).XYZ(), Xc, Yc, Zc);
534   Build.EvalXYZ(pfirst.XYZ(), Xs, Ys, Zs);
535   Build.EvalXYZ(plast.XYZ(), Xe, Ye, Ze);
536   Circle->Init (Zc/GetUnit(), 
537                 gp_XY( Xc/GetUnit(), Yc/GetUnit()), 
538                 gp_XY( Xs/GetUnit(), Ys/GetUnit()), 
539                 gp_XY( Xe/GetUnit(), Ye/GetUnit()));
540   
541   // creation de la Trsf (#124)
542   // il faut tenir compte de l`unite pour la matrice de transformation
543   // (partie translation).
544
545   if (!Build.IsIdentity()){
546     Handle(IGESGeom_TransformationMatrix) TMat = 
547       new IGESGeom_TransformationMatrix;  
548     TMat = Build.MakeTransformation(GetUnit());
549     Circle->InitTransf(TMat);
550   }
551   
552   res = Circle;
553   return res;
554 }
555  
556
557 //=============================================================================
558 // Transfer des Entites Ellipse de Geom vers IGES
559 // TransferCurve
560 //=============================================================================
561
562 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
563 (const Handle(Geom_Ellipse)& start, const Standard_Real Udeb, 
564  const Standard_Real Ufin)
565 {
566
567   Handle(IGESData_IGESEntity) res;
568   if (start.IsNull()) {
569     return res;
570   }
571
572   //#35 rln 22.10.98 BUC60391 face 9
573   //Closed Conic Arc is incorrectly oriented when reading back to CAS.CADE
574   if (Abs (Ufin - Udeb - 2 * M_PI) <= Precision::PConfusion()) {
575     //#53 rln 24.12.98 CCI60005
576     //Trimmed ellipse. To avoid huge weights in B-Spline first rotate it and then convert
577     Handle(Geom_Ellipse) copystart = Handle(Geom_Ellipse)::DownCast (start->Copy());
578     gp_Ax2 pos = copystart->Position();
579     copystart->SetPosition (pos.Rotated (pos.Axis(), gp_Ax3 (pos).Direct() ? Udeb : 2 * M_PI - Udeb));
580     Handle(Geom_BSplineCurve) Bspline;
581     //:q3 abv 17 Mar 99: use GeomConvert_ApproxCurve for precise conversion
582     const Handle(Geom_Curve)& aCopy = copystart; // to avoid ambiguity
583     GeomConvert_ApproxCurve approx (aCopy, Precision::Approximation(), 
584                                     GeomAbs_C1, 100, 6 );
585     if ( approx.HasResult() ) Bspline = approx.Curve();
586     if ( Bspline.IsNull() ) 
587       GeomConvert::CurveToBSplineCurve (copystart, Convert_QuasiAngular);
588     TColStd_Array1OfReal Knots(1, Bspline->NbKnots());
589     Bspline->Knots (Knots);
590     BSplCLib::Reparametrize (Udeb, Udeb + 2 * M_PI, Knots);
591     Bspline->SetKnots (Knots);
592     return TransferCurve (Bspline, Udeb, Ufin);
593   }
594  
595   Handle(IGESGeom_ConicArc) Conic = new IGESGeom_ConicArc;
596   IGESConvGeom_GeomBuilder Build;
597   Standard_Real U1 = Udeb; 
598   Standard_Real U2 = Ufin;
599   if (Abs(Udeb) <= gp::Resolution()) U1 = 0.0;
600
601 // creation du "ConicArc" (#104)
602 // -----------------------------
603
604   Standard_Real xloc,yloc,zloc;
605   start->Elips().Location().Coord(xloc,yloc,zloc);
606   gp_Pnt Loc;
607   Loc.SetCoord(xloc, yloc, zloc);
608   gp_Ax3 Pos = gp_Ax3(start->Elips().Position());
609   Pos.SetLocation(Loc);
610   Build.SetPosition(Pos);
611
612   Standard_Real Xs, Ys, Zs;
613   Standard_Real Xe, Ye, Ze;
614   Build.EvalXYZ((start->Value(U1)).XYZ(), Xs, Ys, Zs);
615   Build.EvalXYZ((start->Value(U2)).XYZ(), Xe, Ye, Ze);
616   gp_Elips2d E2d = gp_Elips2d(gp_Ax22d(gp::Origin2d(), gp::DX2d(), gp::DY2d()),
617                               (start->MajorRadius() / GetUnit()), 
618                               (start->MinorRadius() / GetUnit()));
619   Standard_Real A, B, C, D, E, F;
620   E2d.Coefficients(A, C, B, D, E, F);//#59 rln 29.12.98 PRO17015 face 67
621                                      //gp_Elips2d returns 0.5*K not K 
622
623   Conic->Init (A, 2 * B, C, 2 * D, 2 * E, F, 0., //#59 rln
624                gp_XY( Xs/GetUnit(), Ys/GetUnit()), 
625                gp_XY( Xe/GetUnit(), Ye/GetUnit()));
626
627
628   // creation de la Trsf (#124)
629   // il faut tenir compte de l'unite pour la matrice de transformation
630   // (partie translation).
631
632   if (!Build.IsIdentity()){
633     Handle(IGESGeom_TransformationMatrix) TMat = 
634       new IGESGeom_TransformationMatrix;  
635     TMat = Build.MakeTransformation(GetUnit());
636     Conic->InitTransf(TMat);
637   }
638   res = Conic;
639   return res;
640 }
641  
642
643 //=============================================================================
644 // Transfer des Entites Hyperbola de Geom vers IGES
645 // TransferCurve
646 //=============================================================================
647
648 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
649 (const Handle(Geom_Hyperbola)& start, const Standard_Real Udeb, 
650  const Standard_Real Ufin)
651 {
652   Handle(IGESData_IGESEntity) res;
653   if (start.IsNull()) {
654     return res;
655   }
656
657   Handle(IGESGeom_ConicArc) Conic = new IGESGeom_ConicArc;
658   IGESConvGeom_GeomBuilder Build;
659   Standard_Real U1 = Udeb;
660   Standard_Real U2 = Ufin;
661   if (Precision::IsNegativeInfinite(Udeb)) U1 = -Precision::Infinite();
662   if (Precision::IsPositiveInfinite(Ufin)) U2 = Precision::Infinite();
663
664 // creation du "ConicArc" (#104)
665 // -----------------------------
666   Standard_Real xloc,yloc,zloc;
667   start->Hypr().Location().Coord(xloc,yloc,zloc);
668   gp_Pnt Loc;
669   Loc.SetCoord(xloc, yloc, zloc);
670   gp_Ax3 Pos = gp_Ax3(start->Hypr().Position());
671   Pos.SetLocation(Loc);
672   Build.SetPosition(Pos);
673
674   Standard_Real Xs, Ys, Zs;
675   Standard_Real Xe, Ye, Ze;
676   Build.EvalXYZ((start->Value(U1)).XYZ(), Xs, Ys, Zs);
677   Build.EvalXYZ((start->Value(U2)).XYZ(), Xe, Ye, Ze);
678   gp_Hypr2d H2d = gp_Hypr2d (gp_Ax22d(gp::Origin2d(), gp::DX2d(), gp::DY2d()),
679                              (start->MajorRadius() / GetUnit()), 
680                              (start->MinorRadius() / GetUnit()));
681   Standard_Real A, B, C, D, E, F;
682   H2d.Coefficients(A, C, B, D, E, F);
683
684   Conic->Init (A, B, C, D, E, F, 0., 
685                gp_XY( Xs/GetUnit(), Ys/GetUnit()), 
686                gp_XY( Xe/GetUnit(), Ye/GetUnit()));
687
688
689   // creation de la Trsf (#124)
690   // il faut tenir compte de l'unite pour la matrice de transformation
691   // (partie translation).
692
693   if (!Build.IsIdentity()){
694     Handle(IGESGeom_TransformationMatrix) TMat = 
695       new IGESGeom_TransformationMatrix;  
696     TMat = Build.MakeTransformation(GetUnit());
697     Conic->InitTransf(TMat);
698   }
699   res = Conic;
700   return res;
701 }
702  
703
704 //=============================================================================
705 // Transfer des Entites Parabola de Geom vers IGES
706 // TransferCurve
707 //=============================================================================
708
709 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
710 (const Handle(Geom_Parabola)& start, const Standard_Real Udeb, 
711  const Standard_Real Ufin)
712 {
713   Handle(IGESData_IGESEntity) res;
714   if (start.IsNull()) {
715     return res;
716   }
717
718   Handle(IGESGeom_ConicArc) Conic = new IGESGeom_ConicArc;
719   IGESConvGeom_GeomBuilder Build;
720   Standard_Real U1 = Udeb;
721   Standard_Real U2 = Ufin;
722   if (Precision::IsNegativeInfinite(Udeb)) U1 = -Precision::Infinite();
723   if (Precision::IsPositiveInfinite(Ufin)) U2 = Precision::Infinite();
724
725 // creation du "ConicArc" (#104)
726 // -----------------------------
727   Standard_Real xloc,yloc,zloc;
728   start->Parab().Location().Coord(xloc,yloc,zloc);
729   gp_Pnt Loc;
730   Loc.SetCoord(xloc, yloc, zloc);
731   gp_Ax3 Pos = gp_Ax3(start->Parab().Position());
732   Pos.SetLocation(Loc);
733   Build.SetPosition(Pos);
734
735   Standard_Real Xs, Ys, Zs;
736   Standard_Real Xe, Ye, Ze;
737   Build.EvalXYZ((start->Value(U1)).XYZ(), Xs, Ys, Zs);
738   Build.EvalXYZ((start->Value(U2)).XYZ(), Xe, Ye, Ze);
739   gp_Parab2d P2d = gp_Parab2d (gp_Ax22d(gp::Origin2d(), gp::DX2d(), gp::DY2d()),
740                                (start->Focal()*2.));
741   Standard_Real A, B, C, D, E, F;
742   P2d.Coefficients(A, C, B, D, E, F);
743
744   Conic->Init (A, B, C, D, E, F, 0., 
745                gp_XY( Xs/GetUnit(), Ys/GetUnit()), 
746                gp_XY( Xe/GetUnit(), Ye/GetUnit()));
747
748
749   // creation de la Trsf (#124)
750   // il faut tenir compte de l'unite pour la matrice de transformation
751   // (partie translation).
752
753   if (!Build.IsIdentity()){
754     Handle(IGESGeom_TransformationMatrix) TMat = 
755       new IGESGeom_TransformationMatrix;  
756     TMat = Build.MakeTransformation(GetUnit());
757     Conic->InitTransf(TMat);
758   }
759   res = Conic;
760   return res;
761 }
762  
763
764 //=============================================================================
765 // Transfer des Entites Line de Geom vers IGES
766 // TransferCurve
767 //=============================================================================
768
769 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
770 (const Handle(Geom_Line)& start, const Standard_Real Udeb, 
771  const Standard_Real Ufin)
772 {
773   Handle(IGESData_IGESEntity) res;
774   if (start.IsNull()) {
775     return res;
776   }
777
778   Handle(IGESGeom_Line) Line = new IGESGeom_Line;
779   Standard_Real U1 = Udeb;
780   Standard_Real U2 = Ufin;
781   if (Precision::IsNegativeInfinite(Udeb)) U1 = -Precision::Infinite();
782   if (Precision::IsPositiveInfinite(Ufin)) U2 = Precision::Infinite();
783
784 // creation du "Line" (#110)
785 // -------------------------
786
787   Standard_Real X1,Y1,Z1,X2,Y2,Z2;
788   start->Value(U1).Coord(X1,Y1,Z1);
789   start->Value(U2).Coord(X2,Y2,Z2);
790
791   Line->Init((gp_XYZ(X1/GetUnit(),Y1/GetUnit(),Z1/GetUnit())),
792              (gp_XYZ(X2/GetUnit(),Y2/GetUnit(),Z2/GetUnit())));
793   res = Line;
794   return res;
795 }
796  
797
798 //=============================================================================
799 // Transfer des Entites OffsetCurve de Geom vers IGES
800 // TransferCurve
801 //=============================================================================
802
803 Handle(IGESData_IGESEntity) GeomToIGES_GeomCurve::TransferCurve
804 (const Handle(Geom_OffsetCurve)& start, const Standard_Real Udeb,
805  const Standard_Real Ufin)
806 {
807   Handle(IGESData_IGESEntity) res;
808   if (start.IsNull()) {
809     return res;
810   }
811
812   Handle(IGESGeom_OffsetCurve) OffsetC = new IGESGeom_OffsetCurve;
813   Standard_Real U1 = Udeb;
814   Standard_Real U2 = Ufin;
815   if (Precision::IsNegativeInfinite(Udeb)) U1 = -Precision::Infinite();
816   if (Precision::IsPositiveInfinite(Ufin)) U2 = Precision::Infinite();
817
818   if (Interface_Static::IVal("write.iges.offset.mode") == 0)
819   {
820     res = TransferCurve(GeomConvert::CurveToBSplineCurve(start),U1,U2);
821     return res;
822   }
823
824   Handle(Geom_Curve) Curve = start->BasisCurve();
825   Standard_Real Deb = Curve->FirstParameter();
826   Standard_Real Fin = Curve->LastParameter();
827   //%11 pdn 12.01.98 offset curve should be planar
828   gp_XYZ Normal;
829   if (!IsPlanar(Curve,Normal)) {
830     //%11 pdn 12.01.98 protection against exceptions
831     try{
832       OCC_CATCH_SIGNALS
833       res = TransferCurve(GeomConvert::CurveToBSplineCurve(start),U1,U2);
834       return res;
835     }
836     catch(Standard_Failure const& anException) {
837 #ifdef OCCT_DEBUG
838       std::cout << "writing non-planar offset curve."<<std::endl;
839       std::cout << "Warning: GeomConvert::CurveToBSplineCurve raised an exception: ";
840       anException.Print(std::cout);
841 #endif
842       (void)anException;
843     }
844   }
845
846   Handle(IGESData_IGESEntity) BaseCurve = TransferCurve(Curve, Deb, Fin);
847   Handle(IGESData_IGESEntity) voident;
848   
849   OffsetC->Init( BaseCurve, 1,voident, 0, 0, (start->Offset()/GetUnit()), 0.,
850                 (start->Offset()/GetUnit()), 0.,
851                 start->Direction().XYZ().Reversed(), U1, U2);  //%11 pdn 12.01.99 // valeur (0,0,1) pour l'instant   
852   
853   res = OffsetC;  
854   return res;
855 }