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