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