1 //File Convert_ConicToBSplineCurve.cxx
4 #define No_Standard_OutOfRange
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>
19 #include <BSplCLib.hxx>
20 #include <Precision.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #include <Standard_ConstructionError.hxx>
25 //=======================================================================
26 //function : Convert_ConicToBSplineCurve
28 //=======================================================================
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)
38 poles = new TColgp_HArray1OfPnt2d (1, NbPoles) ;
40 weights = new TColStd_HArray1OfReal (1, NbPoles) ;
43 knots = new TColStd_HArray1OfReal (1, NbKnots) ;
44 mults = new TColStd_HArray1OfInteger(1,NbKnots) ;
49 //=======================================================================
52 //=======================================================================
54 Standard_Integer Convert_ConicToBSplineCurve::Degree () const
59 //=======================================================================
62 //=======================================================================
64 Standard_Integer Convert_ConicToBSplineCurve::NbPoles () const
69 //=======================================================================
72 //=======================================================================
74 Standard_Integer Convert_ConicToBSplineCurve::NbKnots () const
79 //=======================================================================
80 //function : IsPeriodic
82 //=======================================================================
84 Standard_Boolean Convert_ConicToBSplineCurve::IsPeriodic() const
89 //=======================================================================
92 //=======================================================================
94 gp_Pnt2d Convert_ConicToBSplineCurve::Pole
95 (const Standard_Integer Index) const
97 if (Index < 1 || Index > nbPoles)
98 Standard_OutOfRange::Raise(" ");
99 return poles->Value (Index);
103 //=======================================================================
106 //=======================================================================
108 Standard_Real Convert_ConicToBSplineCurve::Weight
109 (const Standard_Integer Index) const
111 if (Index < 1 || Index > nbPoles)
112 Standard_OutOfRange::Raise(" ");
113 return weights->Value (Index);
117 //=======================================================================
120 //=======================================================================
122 Standard_Real Convert_ConicToBSplineCurve::Knot
123 (const Standard_Integer Index) const
125 if (Index < 1 || Index > nbKnots)
126 Standard_OutOfRange::Raise(" ");
127 return knots->Value (Index);
131 //=======================================================================
132 //function : Multiplicity
134 //=======================================================================
136 Standard_Integer Convert_ConicToBSplineCurve::Multiplicity
137 (const Standard_Integer Index) const
139 if (Index < 1 || Index > nbKnots)
140 Standard_OutOfRange::Raise(" ");
141 return mults->Value (Index);
143 //=======================================================================
144 //function : CosAndSinRationalC1
145 //purpose : evaluates U(t) and V(t) such that
148 // cos (theta(t)) = ----------
154 // sin (theta(t)) = ----------
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
161 //=======================================================================
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])
171 BSplCLib::D0(Parameter,
176 BSplCLib::NoWeights(),
180 Result[0] = a_point.Coord(1) ;
181 Result[1] = a_point.Coord(2) ;
185 //=======================================================================
186 //function : CosAndSinQuasiAngular
187 //purpose : evaluates U(t) and V(t) such that
190 // cos (theta(t)) = ----------
196 // sin (theta(t)) = ----------
199 //=======================================================================
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])
214 coeff = (Standard_Real *) &EvalPoles(EvalPoles.Lower()) ;
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
221 param = Parameter * 0.5e0 ;
222 PLib::NoDerivativeEvalPolynomial (param,
230 //=======================================================================
231 //function : function that build the Bspline Representation of
232 // an algorithmic description of the function cos and sin
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)
246 Standard_Integer order,
251 Standard_Real result[2],
255 num_poles = FlatKnots.Length() - order ;
257 if (num_poles != CosNumerator.Length() ||
258 num_poles != SinNumerator.Length() ||
259 num_poles != Denominator.Length() ) {
260 Standard_ConstructionError::Raise();
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,
268 for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
269 Evaluator(parameters(ii),
275 contact_order_array(ii) = 0 ;
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]) ;
284 BSplCLib::Interpolate(Degree,
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) ;
298 //=======================================================================
299 //function : BuildCosAndSin
301 //=======================================================================
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
314 Standard_Real delta = ULast - UFirst,
330 Standard_Integer num_poles,
342 Convert_CosAndSinEvalFunction *EvaluatorPtr=NULL ;
347 switch (Parameterisation) {
348 case Convert_TgtThetaOver2:
350 (Standard_Integer)IntegerPart( 1.2 * delta / PI) + 1;
354 case Convert_TgtThetaOver2_1:
356 if (delta > 0.9999 * PI) {
357 Standard_ConstructionError::Raise() ;
361 case Convert_TgtThetaOver2_2:
363 if (delta > 1.9999 * PI) {
364 Standard_ConstructionError::Raise() ;
369 case Convert_TgtThetaOver2_3:
373 case Convert_TgtThetaOver2_4:
377 case Convert_QuasiAngular:
384 case Convert_RationalC1:
391 case Convert_Polynomial:
400 if (tgt_theta_flag) {
401 alpha = delta / ( 2.0e0 * num_spans) ;
403 num_poles = 2 * num_spans + 1;
407 new TColStd_HArray1OfReal(1,num_poles) ;
409 new TColStd_HArray1OfReal(1,num_poles) ;
411 new TColStd_HArray1OfReal(1,num_poles) ;
413 new TColStd_HArray1OfReal(1,num_spans+1) ;
415 new TColStd_HArray1OfInteger(1,num_spans+1) ;
416 if (tgt_theta_flag) {
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) ;
437 MultsPtr->SetValue(num_spans + 1, Degree + 1) ;
439 else if (Parameterisation != Convert_Polynomial) {
440 alpha = ULast - UFirst ;
442 beta = ULast + UFirst ;
444 cos_beta = Cos(beta) ;
445 sin_beta = Sin(beta) ;
446 num_flat_knots = num_poles + order ;
450 TColStd_Array1OfReal flat_knots(1, num_flat_knots) ;
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) ;
457 for (ii = 1 ; ii <= order ; ii++) {
458 flat_knots(ii) = -alpha ;
459 flat_knots(ii + num_poles) = alpha ;
461 KnotsPtr->SetValue(1,UFirst) ;
462 KnotsPtr->SetValue(num_knots, ULast) ;
463 MultsPtr->SetValue(1,order) ;
464 MultsPtr->SetValue(num_knots,order) ;
466 switch (Parameterisation) {
467 case Convert_QuasiAngular:
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)
476 // c = --- + b = q_param
480 // gamma + ------ - tang gamma
482 // b =------------------------------ = p_param
484 // gamma (tang gamma - gamma)
486 // with gamma = alpha / 2
490 alpha_2 = alpha * 0.5e0 ;
491 p_param = - 1.0e0 / (alpha_2 * alpha_2) ;
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 ;
499 q_param = (1.0e0 / 3.0e0) + p_param ;
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) ;
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 ;
514 case Convert_RationalC1:
515 for (ii = order + 1 ; ii <= num_poles ; ii++) {
516 flat_knots(ii) = 0.0e0 ;
518 KnotsPtr->SetValue(2,UFirst + alpha) ;
519 MultsPtr->SetValue(2,Degree -1) ;
521 alpha_2 = alpha * 0.5e0 ;
522 alpha_4 = alpha * 0.25e0 ;
523 tan_alpha_2 = Tan(alpha_2) ;
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) ;
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;
539 temp_mults(3) = temp_degree + 1;
541 EvaluatorPtr = &CosAndSinRationalC1 ;
546 AlgorithmicCosAndSin(Degree,
553 CosNumeratorPtr->ChangeArray1(),
554 SinNumeratorPtr->ChangeArray1(),
555 DenominatorPtr->ChangeArray1()) ;
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) ;
566 else { // Convert_Polynomial
568 KnotsPtr->SetValue(1, 0.) ;
569 KnotsPtr->SetValue(num_knots, 1.);
570 MultsPtr->SetValue(1, num_poles);
571 MultsPtr->SetValue(num_knots, num_poles);
573 BuildPolynomialCosAndSin(UFirst,ULast,num_poles,
574 CosNumeratorPtr,SinNumeratorPtr,DenominatorPtr);
579 //=======================================================================
580 //function : BuildCosAndSin
582 //=======================================================================
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
593 Standard_Real half_pi,
615 if (Parameterisation != Convert_TgtThetaOver2 &&
616 Parameterisation != Convert_RationalC1) {
617 Standard_ConstructionError::Raise() ;
619 Handle(TColStd_HArray1OfReal) temp_cos_ptr,
621 temp_denominator_ptr,
623 Handle(TColStd_HArray1OfInteger) temp_mults_ptr;
624 if (Parameterisation == Convert_TgtThetaOver2) {
625 BuildCosAndSin(Convert_TgtThetaOver2_3,
630 temp_denominator_ptr,
635 new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
637 new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
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)) ;
645 for (ii = MultsPtr->Lower() ; ii <= MultsPtr->Upper() ; ii++) {
646 MultsPtr->SetValue(ii, Degree) ;
649 else if (Parameterisation == Convert_RationalC1)
651 first_param = 0.0e0 ;
653 BuildCosAndSin(Convert_RationalC1,
658 temp_denominator_ptr,
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) ;
672 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
674 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
676 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
678 half_pi = PI * 0.5e0 ;
680 for (jj = 1 ; jj <= 2 ; jj++) {
681 flat_knots(index) = - half_pi ;
684 for (ii = 1 ; ii <= num_knots ; ii++) {
685 for (jj = 1 ; jj <= Degree -1 ; jj++) {
686 flat_knots(index) = (ii-1) * half_pi ;
692 for (jj = 1 ; jj <= 2 ; jj++) {
693 flat_knots(index) = 2 * PI + half_pi ;
697 new TColStd_HArray1OfReal(1,num_knots) ;
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) ;
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,
713 for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
714 param = parameters(ii) ;
723 temp_cos_ptr->Array1(),
724 temp_denominator_ptr->Array1(),
725 temp_knots_ptr->Array1(),
726 temp_mults_ptr->Array1(),
733 temp_sin_ptr->Array1(),
734 temp_denominator_ptr->Array1(),
735 temp_knots_ptr->Array1(),
736 temp_mults_ptr->Array1(),
742 temp_denominator_ptr->Array1(),
743 BSplCLib::NoWeights(),
744 temp_knots_ptr->Array1(),
745 temp_mults_ptr->Array1(),
747 contact_order_array(ii) = 0 ;
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,
756 BSplCLib::Interpolate(Degree,
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) ;