0024428: Implementation of LGPL license
[occt.git] / src / Convert / Convert_ConicToBSplineCurve.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //JCV 16/10/91
16
17 #define No_Standard_OutOfRange
18
19 #include <Convert_ConicToBSplineCurve.ixx>
20 #include <Convert_CosAndSinEvalFunction.hxx>
21 #include <Convert_PolynomialCosAndSin.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <TColStd_Array1OfInteger.hxx>
24 #include <TColgp_Array1OfPnt2d.hxx>
25 #include <TColgp_Array1OfPnt.hxx>
26 #include <TColStd_HArray1OfReal.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28 #include <TColStd_HArray1OfInteger.hxx>
29 #include <TColgp_HArray1OfPnt2d.hxx>
30
31 #include <PLib.hxx>
32 #include <BSplCLib.hxx>
33 #include <Precision.hxx>
34 #include <gp.hxx>
35 #include <Standard_OutOfRange.hxx>
36 #include <Standard_ConstructionError.hxx>
37
38 //=======================================================================
39 //function : Convert_ConicToBSplineCurve
40 //purpose  : 
41 //=======================================================================
42
43 Convert_ConicToBSplineCurve::Convert_ConicToBSplineCurve 
44   (const Standard_Integer NbPoles,
45    const Standard_Integer NbKnots,
46    const Standard_Integer Degree  ) 
47 : degree (Degree)    ,  nbPoles (NbPoles)   ,  nbKnots (NbKnots)
48   
49
50   if (NbPoles >= 2) {
51     poles    = new TColgp_HArray1OfPnt2d (1, NbPoles)  ;
52    
53     weights  = new TColStd_HArray1OfReal (1, NbPoles)  ;
54   }
55   if (NbKnots >= 2) {
56     knots    = new TColStd_HArray1OfReal (1, NbKnots)  ;
57     mults    = new TColStd_HArray1OfInteger(1,NbKnots) ;
58   }
59 }
60
61
62 //=======================================================================
63 //function : Degree
64 //purpose  : 
65 //=======================================================================
66
67 Standard_Integer Convert_ConicToBSplineCurve::Degree () const 
68 {
69   return degree;
70 }
71
72 //=======================================================================
73 //function : NbPoles
74 //purpose  : 
75 //=======================================================================
76
77 Standard_Integer Convert_ConicToBSplineCurve::NbPoles () const 
78 {
79  return nbPoles; 
80 }
81
82 //=======================================================================
83 //function : NbKnots
84 //purpose  : 
85 //=======================================================================
86
87 Standard_Integer Convert_ConicToBSplineCurve::NbKnots () const 
88 {
89   return nbKnots;
90 }
91
92 //=======================================================================
93 //function : IsPeriodic
94 //purpose  : 
95 //=======================================================================
96
97 Standard_Boolean Convert_ConicToBSplineCurve::IsPeriodic() const 
98 {
99   return isperiodic;
100 }
101
102 //=======================================================================
103 //function : Pole
104 //purpose  : 
105 //=======================================================================
106
107 gp_Pnt2d Convert_ConicToBSplineCurve::Pole 
108   (const Standard_Integer Index) const 
109 {
110   if (Index < 1 || Index > nbPoles)
111     Standard_OutOfRange::Raise(" ");
112   return poles->Value (Index);
113 }
114
115
116 //=======================================================================
117 //function : Weight
118 //purpose  : 
119 //=======================================================================
120
121 Standard_Real Convert_ConicToBSplineCurve::Weight 
122   (const Standard_Integer Index) const 
123 {
124   if (Index < 1 || Index > nbPoles)
125     Standard_OutOfRange::Raise(" ");
126   return weights->Value (Index);
127 }
128
129
130 //=======================================================================
131 //function : Knot
132 //purpose  : 
133 //=======================================================================
134
135 Standard_Real Convert_ConicToBSplineCurve::Knot 
136   (const Standard_Integer Index) const 
137 {
138   if (Index < 1 || Index > nbKnots)
139     Standard_OutOfRange::Raise(" ");
140   return knots->Value (Index);
141 }
142
143
144 //=======================================================================
145 //function : Multiplicity
146 //purpose  : 
147 //=======================================================================
148
149 Standard_Integer Convert_ConicToBSplineCurve::Multiplicity
150   (const Standard_Integer Index) const 
151 {
152   if (Index < 1 || Index > nbKnots)
153     Standard_OutOfRange::Raise(" ");
154   return mults->Value (Index);
155 }
156 //=======================================================================
157 //function : CosAndSinRationalC1
158 //purpose  : evaluates U(t) and V(t) such that
159 //                      2      2
160 //                     U   -  V 
161 //   cos (theta(t)) = ----------
162 //                      2      2
163 //                     U   +  V 
164 //
165
166 //                      2 * U*V
167 //   sin (theta(t)) = ----------
168 //                      2      2
169 //                     U   +  V 
170 //                                                    2     2
171 //  such that the derivative at the domain bounds of U   + V   is 0.0e0 
172 //  with is helpfull when having to make a C1 BSpline  by merging two
173 //  BSpline toghether
174 //=======================================================================
175
176 void CosAndSinRationalC1(Standard_Real Parameter,
177                           const Standard_Integer         EvalDegree,
178                           const TColgp_Array1OfPnt2d&    EvalPoles,
179                           const TColStd_Array1OfReal&    EvalKnots,
180                           const TColStd_Array1OfInteger& EvalMults,
181                           Standard_Real Result[2]) 
182 {
183  gp_Pnt2d a_point ;
184  BSplCLib::D0(Parameter,
185               0,
186               EvalDegree,
187               Standard_False,
188               EvalPoles,
189               BSplCLib::NoWeights(),
190               EvalKnots,
191               EvalMults,
192               a_point) ;
193  Result[0] = a_point.Coord(1) ;
194  Result[1] = a_point.Coord(2) ;
195 }
196       
197
198 //=======================================================================
199 //function : CosAndSinQuasiAngular
200 //purpose  : evaluates U(t) and V(t) such that
201 //                      2      2
202 //                     U   -  V 
203 //   cos (theta(t)) = ----------
204 //                      2      2
205 //                     U   +  V 
206 //
207
208 //                      2 * U*V
209 //   sin (theta(t)) = ----------
210 //                      2      2
211 //                     U   +  V 
212 //=======================================================================
213
214 void  CosAndSinQuasiAngular(Standard_Real  Parameter,
215                             const Standard_Integer         EvalDegree,
216                             const TColgp_Array1OfPnt2d&    EvalPoles,
217 //                          const TColStd_Array1OfReal&    EvalKnots,
218                             const TColStd_Array1OfReal&    ,
219 //                          const TColStd_Array1OfInteger& EvalMults,
220                             const TColStd_Array1OfInteger& ,
221                             Standard_Real  Result[2])
222 {
223   Standard_Real 
224   param,
225   *coeff ;
226  
227    coeff = (Standard_Real *) &EvalPoles(EvalPoles.Lower()) ;
228 //
229 //   rational_function_coeff represent a rational approximation
230 //   of U ---> cotan( PI * U /2) between [0 1] 
231 //   rational_function_coeff[i][0] is the denominator
232 //   rational_function_coeff[i][1] is the numerator
233 //   
234    param = Parameter * 0.5e0 ;
235   PLib::NoDerivativeEvalPolynomial (param,
236                                     EvalDegree,
237                                     2,
238                                     EvalDegree << 1,
239                                     coeff[0],
240                                     Result[0]) ;
241 }
242    
243 //=======================================================================
244 //function : function that build the Bspline Representation of 
245 // an algorithmic description of the function cos and sin
246 //purpose  : 
247 //=======================================================================
248 void AlgorithmicCosAndSin(Standard_Integer               Degree,
249                           const TColStd_Array1OfReal&    FlatKnots,
250                           const Standard_Integer         EvalDegree,
251                           const TColgp_Array1OfPnt2d&    EvalPoles,
252                           const TColStd_Array1OfReal&    EvalKnots,
253                           const TColStd_Array1OfInteger& EvalMults,
254                           Convert_CosAndSinEvalFunction  Evaluator,
255                           TColStd_Array1OfReal&          CosNumerator,
256                           TColStd_Array1OfReal&          SinNumerator,
257                           TColStd_Array1OfReal&          Denominator) 
258 {
259    Standard_Integer order,
260    num_poles,
261    pivot_index_problem,
262    ii;
263  
264    Standard_Real  result[2],
265    inverse ;
266
267    order = Degree + 1 ;
268    num_poles = FlatKnots.Length() - order ;
269
270    if (num_poles != CosNumerator.Length() ||
271        num_poles != SinNumerator.Length() ||
272        num_poles != Denominator.Length() ) {
273       Standard_ConstructionError::Raise();
274       }
275    TColStd_Array1OfReal      parameters(1,num_poles)  ;
276    TColgp_Array1OfPnt        poles_array(1,num_poles) ;
277    TColStd_Array1OfInteger   contact_order_array(1,num_poles) ;  
278    BSplCLib::BuildSchoenbergPoints(Degree,
279                                    FlatKnots,
280                                    parameters) ;
281    for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
282      Evaluator(parameters(ii),
283                EvalDegree,
284                EvalPoles,
285                EvalKnots,
286                EvalMults,
287                result) ;
288      contact_order_array(ii) = 0 ;
289      
290      poles_array(ii).SetCoord(1,
291                               (result[1]*result[1] - result[0]*result[0]));
292      poles_array(ii).SetCoord(2,
293                               2.0e0  * result[1]* result[0]) ;
294      poles_array(ii).SetCoord(3,
295                               result[1]*result[1] + result[0] * result[0]) ;
296    }
297     BSplCLib::Interpolate(Degree,
298                           FlatKnots,
299                           parameters,
300                           contact_order_array,
301                           poles_array,
302                           pivot_index_problem) ;
303     for (ii = 1 ; ii <= num_poles ; ii++) {
304       inverse = 1.0e0 / poles_array(ii).Coord(3) ;
305       CosNumerator(ii) = poles_array(ii).Coord(1) * inverse ;
306       SinNumerator(ii) = poles_array(ii).Coord(2) * inverse ;
307       Denominator(ii)  = poles_array(ii).Coord(3) ;
308     }
309  }
310
311 //=======================================================================
312 //function : BuildCosAndSin
313 //purpose  : 
314 //=======================================================================
315
316 void Convert_ConicToBSplineCurve::BuildCosAndSin(
317           const Convert_ParameterisationType     Parameterisation,
318           const Standard_Real                    UFirst,
319           const Standard_Real                    ULast,
320           Handle(TColStd_HArray1OfReal)&         CosNumeratorPtr,
321           Handle(TColStd_HArray1OfReal)&         SinNumeratorPtr,
322           Handle(TColStd_HArray1OfReal)&         DenominatorPtr,
323           Standard_Integer&                      Degree,
324           Handle(TColStd_HArray1OfReal)&         KnotsPtr,
325           Handle(TColStd_HArray1OfInteger)&      MultsPtr)  const 
326 {
327   Standard_Real delta = ULast - UFirst,
328   direct,
329   inverse,
330   value1,
331   value2,
332   cos_beta,
333   sin_beta,
334   alpha=0,
335   alpha_2,
336   alpha_4,
337   tan_alpha_2,
338   beta,
339   p_param,
340   q_param,
341   param ;
342
343   Standard_Integer num_poles = 0,
344   ii,
345   jj,
346   num_knots = 1,
347   num_spans = 1,
348   num_flat_knots,
349   num_temp_knots,
350   temp_degree = 0,
351   tgt_theta_flag,
352   num_temp_poles,
353   order  = 0;
354
355   Convert_CosAndSinEvalFunction *EvaluatorPtr=NULL ;
356
357   tgt_theta_flag = 0 ;
358
359
360   switch (Parameterisation) {
361   case Convert_TgtThetaOver2: 
362     num_spans =
363       (Standard_Integer)IntegerPart( 1.2 * delta / M_PI) + 1;
364     
365     tgt_theta_flag = 1 ;
366     break ;
367   case Convert_TgtThetaOver2_1:
368     num_spans = 1 ;
369     if (delta > 0.9999 * M_PI) {
370       Standard_ConstructionError::Raise() ; 
371       }
372     tgt_theta_flag = 1 ;
373     break ;
374   case Convert_TgtThetaOver2_2:
375     num_spans = 2 ;
376     if (delta > 1.9999 * M_PI) {
377       Standard_ConstructionError::Raise() ;
378       }
379     tgt_theta_flag = 1 ;
380     break ;
381   
382   case Convert_TgtThetaOver2_3:
383     num_spans = 3 ;
384     tgt_theta_flag = 1 ;
385     break ;
386   case Convert_TgtThetaOver2_4:
387     num_spans = 4 ;
388     tgt_theta_flag = 1 ;
389     break ; 
390   case Convert_QuasiAngular:
391     num_poles = 7 ;
392     Degree    = 6 ;
393     num_spans = 1 ;
394     num_knots = 2 ;
395     order = Degree + 1 ;
396     break ;
397    case Convert_RationalC1:
398     Degree    = 4 ;
399     order = Degree + 1 ; 
400     num_poles = 8 ;
401     num_knots = 3 ;
402     num_spans = 2 ;
403     break ;
404    case Convert_Polynomial:
405     Degree    = 7 ;
406     num_poles = 8 ;
407     num_knots = 2 ;
408     num_spans = 1 ;
409     break ;
410   default:
411     break ;
412   }
413   if (tgt_theta_flag) {
414     alpha = delta / ( 2.0e0 * num_spans) ;    
415     Degree = 2 ;
416     num_poles = 2 * num_spans + 1;
417   }  
418   
419   CosNumeratorPtr = 
420     new TColStd_HArray1OfReal(1,num_poles) ;
421   SinNumeratorPtr =
422     new TColStd_HArray1OfReal(1,num_poles) ;      
423   DenominatorPtr =
424     new TColStd_HArray1OfReal(1,num_poles) ;      
425   KnotsPtr = 
426     new TColStd_HArray1OfReal(1,num_spans+1) ;
427   MultsPtr =
428     new TColStd_HArray1OfInteger(1,num_spans+1) ;
429   if (tgt_theta_flag) {
430
431     param = UFirst ;
432     CosNumeratorPtr->SetValue(1,Cos(UFirst)) ;
433     SinNumeratorPtr->SetValue(1,Sin(UFirst)) ;
434     DenominatorPtr ->SetValue(1,1.0e0) ;
435     KnotsPtr->SetValue(1,param) ;
436     MultsPtr->SetValue(1,Degree + 1) ;
437     direct = Cos(alpha) ;
438     inverse = 1.0e0 / direct ;
439     for (ii = 1 ; ii <= num_spans ; ii++ ) {
440       CosNumeratorPtr->SetValue(2 * ii, inverse * Cos(param + alpha)) ;
441       SinNumeratorPtr->SetValue(2 * ii, inverse * Sin(param + alpha)) ;
442       DenominatorPtr->SetValue(2 * ii,  direct) ; 
443       CosNumeratorPtr->SetValue(2 * ii + 1, Cos(param + 2 * alpha)) ;
444       SinNumeratorPtr->SetValue(2 * ii + 1, Sin(param + 2 * alpha)) ;
445       DenominatorPtr->SetValue(2 * ii + 1,  1.0e0) ;
446       KnotsPtr->SetValue(ii + 1, param + 2 * alpha) ;
447       MultsPtr->SetValue(ii + 1, 2) ;
448       param += 2 * alpha ;
449     }
450     MultsPtr->SetValue(num_spans + 1, Degree + 1) ;
451   }
452   else if (Parameterisation != Convert_Polynomial) {
453     alpha = ULast - UFirst ;
454     alpha *= 0.5e0 ;
455     beta = ULast + UFirst ;
456     beta *= 0.5e0 ;
457     cos_beta = Cos(beta) ;
458     sin_beta = Sin(beta) ;
459     num_flat_knots = num_poles + order ;
460
461     num_temp_poles = 4 ;
462     num_temp_knots = 3 ;
463     TColStd_Array1OfReal   flat_knots(1, num_flat_knots) ;
464     
465
466     TColgp_Array1OfPnt2d    temp_poles(1,num_temp_poles)  ;
467     TColStd_Array1OfReal    temp_knots(1,num_temp_knots)  ;
468     TColStd_Array1OfInteger temp_mults(1,num_temp_knots) ;
469
470     for (ii = 1 ; ii <= order ; ii++) {
471       flat_knots(ii) = -alpha ;
472       flat_knots(ii + num_poles) = alpha ;
473     }
474     KnotsPtr->SetValue(1,UFirst) ;
475     KnotsPtr->SetValue(num_knots, ULast) ;
476     MultsPtr->SetValue(1,order) ;
477     MultsPtr->SetValue(num_knots,order) ;
478     
479     switch (Parameterisation) {
480     case Convert_QuasiAngular:
481 //
482 //    we code here in temp_poles(xx).Coord(1) the following function V(t) 
483 //   and in temp_poles(xx).Coord(2) the function U(t) 
484 //                     3
485 //       V(t) = t + c t
486 //                     2
487 //       U(t) = 1 + b t
488 //            1
489 //       c = ---  + b   = q_param
490 //            3 
491 //                          3
492 //                     gamma
493 //            gamma +  ------  - tang gamma
494 //                      3
495 //       b =------------------------------    = p_param
496 //                 2 
497 //            gamma  (tang gamma - gamma) 
498 //
499 //     with gamma = alpha / 2
500 //
501 //
502      
503       alpha_2 = alpha * 0.5e0 ;
504       p_param = - 1.0e0 / (alpha_2 * alpha_2) ;
505      
506       if (alpha_2 <  M_PI * 0.5e0) {
507         tan_alpha_2 = Tan(alpha_2) ;
508         value1 = 3.0e0 * (tan_alpha_2 - alpha_2) ;
509         value1 = alpha_2 / value1 ;
510         p_param += value1 ;
511       }
512       q_param = (1.0e0 / 3.0e0)  + p_param ;
513       
514       
515       temp_degree = 3 ;
516       temp_poles(1).SetCoord(1,0.0e0);
517       temp_poles(2).SetCoord(1,1.0e0);
518       temp_poles(3).SetCoord(1,0.0e0) ;
519       temp_poles(4).SetCoord(1,q_param) ;
520
521       temp_poles(1).SetCoord(2, 1.0e0) ;
522       temp_poles(2).SetCoord(2, 0.0e0) ;
523       temp_poles(3).SetCoord(2, p_param) ;
524       temp_poles(4).SetCoord(2, 0.0e0);
525       EvaluatorPtr = &CosAndSinQuasiAngular ;
526       break ;
527     case  Convert_RationalC1:
528       for (ii = order + 1 ; ii <= num_poles ; ii++) {
529         flat_knots(ii) = 0.0e0 ;
530       }
531       KnotsPtr->SetValue(2,UFirst + alpha) ;
532       MultsPtr->SetValue(2,Degree -1) ;
533       temp_degree = 2 ;   
534       alpha_2 = alpha * 0.5e0 ;
535       alpha_4 = alpha * 0.25e0 ;
536       tan_alpha_2 = Tan(alpha_2) ;
537       jj = 1 ;
538       for (ii = 1 ; ii <= 2 ; ii++) {
539         temp_poles(1+ ii).SetCoord(2,1.0e0 + alpha_4 * tan_alpha_2) ;
540         temp_poles(jj).SetCoord(2,1.e0) ;
541         jj += 3 ;
542       }
543       temp_poles(1).SetCoord(1,-tan_alpha_2) ;  
544       temp_poles(2).SetCoord(1,alpha_4 - tan_alpha_2) ; 
545       temp_poles(3).SetCoord(1,-alpha_4 + tan_alpha_2) ; 
546       temp_poles(4).SetCoord(1,tan_alpha_2) ; 
547       temp_knots(1) = -alpha ;
548       temp_knots(2) = 0.0e0 ;
549       temp_knots(3) = alpha ;
550       temp_mults(1) = temp_degree + 1;
551       temp_mults(2) = 1 ;
552       temp_mults(3) = temp_degree + 1;
553      
554       EvaluatorPtr = &CosAndSinRationalC1 ;
555       break ;
556     default: 
557       break ;
558     }
559     AlgorithmicCosAndSin(Degree,
560                          flat_knots,
561                          temp_degree,
562                          temp_poles,
563                          temp_knots,
564                          temp_mults,
565                          *EvaluatorPtr,
566                          CosNumeratorPtr->ChangeArray1(),
567                          SinNumeratorPtr->ChangeArray1(),
568                          DenominatorPtr->ChangeArray1()) ;
569
570     for (ii = 1 ; ii <= num_poles ; ii++) {
571        value1 = cos_beta * CosNumeratorPtr->Value(ii) -
572          sin_beta * SinNumeratorPtr->Value(ii) ;
573        value2 = sin_beta * CosNumeratorPtr->Value(ii) +
574          cos_beta * SinNumeratorPtr->Value(ii) ;
575        CosNumeratorPtr->SetValue(ii,value1) ;
576        SinNumeratorPtr->SetValue(ii,value2) ;
577      }
578   }
579   else { // Convert_Polynomial
580
581     KnotsPtr->SetValue(1, 0.) ;
582     KnotsPtr->SetValue(num_knots, 1.);
583     MultsPtr->SetValue(1, num_poles);
584     MultsPtr->SetValue(num_knots, num_poles);
585     
586     BuildPolynomialCosAndSin(UFirst,ULast,num_poles,
587                              CosNumeratorPtr,SinNumeratorPtr,DenominatorPtr);
588   }
589
590
591 }
592 //=======================================================================
593 //function : BuildCosAndSin
594 //purpose  : 
595 //=======================================================================
596
597 void Convert_ConicToBSplineCurve::BuildCosAndSin(
598           const Convert_ParameterisationType     Parameterisation,
599           Handle(TColStd_HArray1OfReal)&         CosNumeratorPtr,
600           Handle(TColStd_HArray1OfReal)&         SinNumeratorPtr,
601           Handle(TColStd_HArray1OfReal)&         DenominatorPtr,
602           Standard_Integer&                      Degree,
603           Handle(TColStd_HArray1OfReal)&         KnotsPtr,
604           Handle(TColStd_HArray1OfInteger)&      MultsPtr)  const 
605 {
606   Standard_Real half_pi,
607   param,
608   first_param,
609   last_param,
610 //  direct,
611   inverse,
612   value1,
613   value2,
614   value3 ;
615
616   Standard_Integer 
617   ii,
618   jj,
619   index,
620   num_poles,
621   num_periodic_poles,
622   temp_degree,
623   pivot_index_problem,
624   num_flat_knots,
625   num_knots,
626   order ;
627
628   if (Parameterisation != Convert_TgtThetaOver2 &&
629       Parameterisation != Convert_RationalC1) {
630       Standard_ConstructionError::Raise() ;
631       }
632   Handle(TColStd_HArray1OfReal) temp_cos_ptr,
633   temp_sin_ptr,
634   temp_denominator_ptr,
635   temp_knots_ptr;
636   Handle(TColStd_HArray1OfInteger)  temp_mults_ptr;
637   if (Parameterisation == Convert_TgtThetaOver2) {
638     BuildCosAndSin(Convert_TgtThetaOver2_3,
639                    0.0e0,
640                    2 * M_PI,
641                    temp_cos_ptr,
642                    temp_sin_ptr,
643                    temp_denominator_ptr,
644                    Degree,
645                    KnotsPtr,
646                    MultsPtr) ;
647      CosNumeratorPtr =
648        new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
649      SinNumeratorPtr =
650         new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
651      DenominatorPtr =
652         new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ; 
653      for (ii = temp_cos_ptr->Lower()  ; ii <= temp_cos_ptr->Upper()-1 ; ii++) {
654        CosNumeratorPtr->SetValue(ii,temp_cos_ptr->Value(ii)) ;
655        SinNumeratorPtr->SetValue(ii,temp_sin_ptr->Value(ii)) ;
656        DenominatorPtr->SetValue(ii,temp_denominator_ptr->Value(ii)) ;
657      }
658     for (ii = MultsPtr->Lower() ; ii <= MultsPtr->Upper() ; ii++) {
659       MultsPtr->SetValue(ii, Degree) ;
660     }
661   }
662   else if (Parameterisation == Convert_RationalC1) 
663     {
664      first_param = 0.0e0 ;
665      last_param  = M_PI ;
666      BuildCosAndSin(Convert_RationalC1,
667                    first_param,
668                    last_param,
669                    temp_cos_ptr,
670                    temp_sin_ptr,
671                    temp_denominator_ptr,
672                    temp_degree,
673                    temp_knots_ptr,
674                    temp_mults_ptr) ;
675
676
677      Degree = 4 ;
678      order = Degree + 1 ;
679      num_knots = 5 ;
680      num_flat_knots = (Degree -1) * num_knots + 2 * 2 ;
681      num_poles = num_flat_knots - order ;
682      num_periodic_poles = num_poles - 2 ;
683      TColStd_Array1OfReal  flat_knots(1,num_flat_knots) ;
684      CosNumeratorPtr = 
685       new TColStd_HArray1OfReal(1,num_periodic_poles) ;
686      SinNumeratorPtr = 
687       new TColStd_HArray1OfReal(1,num_periodic_poles) ;
688      DenominatorPtr = 
689       new TColStd_HArray1OfReal(1,num_periodic_poles) ;
690     
691      half_pi = M_PI * 0.5e0 ;
692      index = 1 ;
693      for (jj = 1 ; jj <= 2 ; jj++) {
694          flat_knots(index) = -  half_pi  ;
695          index += 1 ;
696        }
697      for (ii = 1 ; ii <= num_knots ; ii++) {
698        for (jj = 1 ; jj <= Degree -1 ; jj++) {
699          flat_knots(index) = (ii-1) * half_pi ;
700
701          index += 1 ;
702
703        }
704      }
705      for (jj = 1 ; jj <= 2 ; jj++) {
706          flat_knots(index) = 2 * M_PI +  half_pi  ;
707          index += 1 ;
708        }
709      KnotsPtr = 
710        new TColStd_HArray1OfReal(1,num_knots) ;
711      MultsPtr =
712        new TColStd_HArray1OfInteger(1,num_knots) ;
713      for ( ii = 1 ; ii <= num_knots  ; ii++) { 
714        KnotsPtr->SetValue(ii, (ii-1) * half_pi) ;
715        MultsPtr->SetValue(ii, Degree-1) ;
716      }
717      order = degree + 1 ;
718
719      TColStd_Array1OfReal      parameters(1,num_poles)  ;
720      TColgp_Array1OfPnt        poles_array(1,num_poles) ;
721      TColStd_Array1OfInteger   contact_order_array(1,num_poles) ;  
722      BSplCLib::BuildSchoenbergPoints(Degree,
723                                      flat_knots,
724                                      parameters) ;
725      inverse = 1.0e0 ;
726      for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
727        param = parameters(ii) ;
728        if (param > M_PI) {
729          inverse = -1.0e0 ;
730          param -= M_PI ;
731        }
732        BSplCLib::D0(param,
733                     0,
734                     temp_degree,
735                     Standard_False,
736                     temp_cos_ptr->Array1(),
737                     temp_denominator_ptr->Array1(),
738                     temp_knots_ptr->Array1(),
739                     temp_mults_ptr->Array1(),
740                     value1) ;
741
742        BSplCLib::D0(param,
743                     0,
744                     temp_degree,
745                     Standard_False,
746                     temp_sin_ptr->Array1(),
747                     temp_denominator_ptr->Array1(),
748                     temp_knots_ptr->Array1(),
749                     temp_mults_ptr->Array1(),
750                     value2) ;
751        BSplCLib::D0(param,
752                     0,
753                     temp_degree,
754                     Standard_False,
755                     temp_denominator_ptr->Array1(),
756                     BSplCLib::NoWeights(),
757                     temp_knots_ptr->Array1(),
758                     temp_mults_ptr->Array1(),
759                     value3) ;
760      contact_order_array(ii) = 0 ;
761      
762      poles_array(ii).SetCoord(1,
763                               value1 * value3 * inverse) ;
764      poles_array(ii).SetCoord(2,
765                               value2 * value3 * inverse) ;
766      poles_array(ii).SetCoord(3,
767                               value3) ;
768    }
769     BSplCLib::Interpolate(Degree,
770                           flat_knots,
771                           parameters,
772                           contact_order_array,
773                           poles_array,
774                           pivot_index_problem) ;
775     for (ii = 1 ; ii <= num_periodic_poles ; ii++) {
776       inverse = 1.0e0 / poles_array(ii).Coord(3) ;
777       CosNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(1) * inverse ;
778       SinNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(2) * inverse ;
779       DenominatorPtr->ChangeArray1()(ii)  = poles_array(ii).Coord(3) ;
780     }
781  }
782 }
783
784
785