1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
21 #define No_Standard_OutOfRange
23 #include <Convert_ConicToBSplineCurve.ixx>
24 #include <Convert_CosAndSinEvalFunction.hxx>
25 #include <Convert_PolynomialCosAndSin.hxx>
26 #include <TColStd_Array1OfReal.hxx>
27 #include <TColStd_Array1OfInteger.hxx>
28 #include <TColgp_Array1OfPnt2d.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColStd_HArray1OfReal.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColgp_HArray1OfPnt2d.hxx>
36 #include <BSplCLib.hxx>
37 #include <Precision.hxx>
39 #include <Standard_OutOfRange.hxx>
40 #include <Standard_ConstructionError.hxx>
42 //=======================================================================
43 //function : Convert_ConicToBSplineCurve
45 //=======================================================================
47 Convert_ConicToBSplineCurve::Convert_ConicToBSplineCurve
48 (const Standard_Integer NbPoles,
49 const Standard_Integer NbKnots,
50 const Standard_Integer Degree )
51 : degree (Degree) , nbPoles (NbPoles) , nbKnots (NbKnots)
55 poles = new TColgp_HArray1OfPnt2d (1, NbPoles) ;
57 weights = new TColStd_HArray1OfReal (1, NbPoles) ;
60 knots = new TColStd_HArray1OfReal (1, NbKnots) ;
61 mults = new TColStd_HArray1OfInteger(1,NbKnots) ;
66 //=======================================================================
69 //=======================================================================
71 Standard_Integer Convert_ConicToBSplineCurve::Degree () const
76 //=======================================================================
79 //=======================================================================
81 Standard_Integer Convert_ConicToBSplineCurve::NbPoles () const
86 //=======================================================================
89 //=======================================================================
91 Standard_Integer Convert_ConicToBSplineCurve::NbKnots () const
96 //=======================================================================
97 //function : IsPeriodic
99 //=======================================================================
101 Standard_Boolean Convert_ConicToBSplineCurve::IsPeriodic() const
106 //=======================================================================
109 //=======================================================================
111 gp_Pnt2d Convert_ConicToBSplineCurve::Pole
112 (const Standard_Integer Index) const
114 if (Index < 1 || Index > nbPoles)
115 Standard_OutOfRange::Raise(" ");
116 return poles->Value (Index);
120 //=======================================================================
123 //=======================================================================
125 Standard_Real Convert_ConicToBSplineCurve::Weight
126 (const Standard_Integer Index) const
128 if (Index < 1 || Index > nbPoles)
129 Standard_OutOfRange::Raise(" ");
130 return weights->Value (Index);
134 //=======================================================================
137 //=======================================================================
139 Standard_Real Convert_ConicToBSplineCurve::Knot
140 (const Standard_Integer Index) const
142 if (Index < 1 || Index > nbKnots)
143 Standard_OutOfRange::Raise(" ");
144 return knots->Value (Index);
148 //=======================================================================
149 //function : Multiplicity
151 //=======================================================================
153 Standard_Integer Convert_ConicToBSplineCurve::Multiplicity
154 (const Standard_Integer Index) const
156 if (Index < 1 || Index > nbKnots)
157 Standard_OutOfRange::Raise(" ");
158 return mults->Value (Index);
160 //=======================================================================
161 //function : CosAndSinRationalC1
162 //purpose : evaluates U(t) and V(t) such that
165 // cos (theta(t)) = ----------
171 // sin (theta(t)) = ----------
175 // such that the derivative at the domain bounds of U + V is 0.0e0
176 // with is helpfull when having to make a C1 BSpline by merging two
178 //=======================================================================
180 void CosAndSinRationalC1(Standard_Real Parameter,
181 const Standard_Integer EvalDegree,
182 const TColgp_Array1OfPnt2d& EvalPoles,
183 const TColStd_Array1OfReal& EvalKnots,
184 const TColStd_Array1OfInteger& EvalMults,
185 Standard_Real Result[2])
188 BSplCLib::D0(Parameter,
193 BSplCLib::NoWeights(),
197 Result[0] = a_point.Coord(1) ;
198 Result[1] = a_point.Coord(2) ;
202 //=======================================================================
203 //function : CosAndSinQuasiAngular
204 //purpose : evaluates U(t) and V(t) such that
207 // cos (theta(t)) = ----------
213 // sin (theta(t)) = ----------
216 //=======================================================================
218 void CosAndSinQuasiAngular(Standard_Real Parameter,
219 const Standard_Integer EvalDegree,
220 const TColgp_Array1OfPnt2d& EvalPoles,
221 // const TColStd_Array1OfReal& EvalKnots,
222 const TColStd_Array1OfReal& ,
223 // const TColStd_Array1OfInteger& EvalMults,
224 const TColStd_Array1OfInteger& ,
225 Standard_Real Result[2])
231 coeff = (Standard_Real *) &EvalPoles(EvalPoles.Lower()) ;
233 // rational_function_coeff represent a rational approximation
234 // of U ---> cotan( PI * U /2) between [0 1]
235 // rational_function_coeff[i][0] is the denominator
236 // rational_function_coeff[i][1] is the numerator
238 param = Parameter * 0.5e0 ;
239 PLib::NoDerivativeEvalPolynomial (param,
247 //=======================================================================
248 //function : function that build the Bspline Representation of
249 // an algorithmic description of the function cos and sin
251 //=======================================================================
252 void AlgorithmicCosAndSin(Standard_Integer Degree,
253 const TColStd_Array1OfReal& FlatKnots,
254 const Standard_Integer EvalDegree,
255 const TColgp_Array1OfPnt2d& EvalPoles,
256 const TColStd_Array1OfReal& EvalKnots,
257 const TColStd_Array1OfInteger& EvalMults,
258 Convert_CosAndSinEvalFunction Evaluator,
259 TColStd_Array1OfReal& CosNumerator,
260 TColStd_Array1OfReal& SinNumerator,
261 TColStd_Array1OfReal& Denominator)
263 Standard_Integer order,
268 Standard_Real result[2],
272 num_poles = FlatKnots.Length() - order ;
274 if (num_poles != CosNumerator.Length() ||
275 num_poles != SinNumerator.Length() ||
276 num_poles != Denominator.Length() ) {
277 Standard_ConstructionError::Raise();
279 TColStd_Array1OfReal parameters(1,num_poles) ;
280 TColgp_Array1OfPnt poles_array(1,num_poles) ;
281 TColStd_Array1OfInteger contact_order_array(1,num_poles) ;
282 BSplCLib::BuildSchoenbergPoints(Degree,
285 for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
286 Evaluator(parameters(ii),
292 contact_order_array(ii) = 0 ;
294 poles_array(ii).SetCoord(1,
295 (result[1]*result[1] - result[0]*result[0]));
296 poles_array(ii).SetCoord(2,
297 2.0e0 * result[1]* result[0]) ;
298 poles_array(ii).SetCoord(3,
299 result[1]*result[1] + result[0] * result[0]) ;
301 BSplCLib::Interpolate(Degree,
306 pivot_index_problem) ;
307 for (ii = 1 ; ii <= num_poles ; ii++) {
308 inverse = 1.0e0 / poles_array(ii).Coord(3) ;
309 CosNumerator(ii) = poles_array(ii).Coord(1) * inverse ;
310 SinNumerator(ii) = poles_array(ii).Coord(2) * inverse ;
311 Denominator(ii) = poles_array(ii).Coord(3) ;
315 //=======================================================================
316 //function : BuildCosAndSin
318 //=======================================================================
320 void Convert_ConicToBSplineCurve::BuildCosAndSin(
321 const Convert_ParameterisationType Parameterisation,
322 const Standard_Real UFirst,
323 const Standard_Real ULast,
324 Handle(TColStd_HArray1OfReal)& CosNumeratorPtr,
325 Handle(TColStd_HArray1OfReal)& SinNumeratorPtr,
326 Handle(TColStd_HArray1OfReal)& DenominatorPtr,
327 Standard_Integer& Degree,
328 Handle(TColStd_HArray1OfReal)& KnotsPtr,
329 Handle(TColStd_HArray1OfInteger)& MultsPtr) const
331 Standard_Real delta = ULast - UFirst,
347 Standard_Integer num_poles,
359 Convert_CosAndSinEvalFunction *EvaluatorPtr=NULL ;
364 switch (Parameterisation) {
365 case Convert_TgtThetaOver2:
367 (Standard_Integer)IntegerPart( 1.2 * delta / M_PI) + 1;
371 case Convert_TgtThetaOver2_1:
373 if (delta > 0.9999 * M_PI) {
374 Standard_ConstructionError::Raise() ;
378 case Convert_TgtThetaOver2_2:
380 if (delta > 1.9999 * M_PI) {
381 Standard_ConstructionError::Raise() ;
386 case Convert_TgtThetaOver2_3:
390 case Convert_TgtThetaOver2_4:
394 case Convert_QuasiAngular:
401 case Convert_RationalC1:
408 case Convert_Polynomial:
417 if (tgt_theta_flag) {
418 alpha = delta / ( 2.0e0 * num_spans) ;
420 num_poles = 2 * num_spans + 1;
424 new TColStd_HArray1OfReal(1,num_poles) ;
426 new TColStd_HArray1OfReal(1,num_poles) ;
428 new TColStd_HArray1OfReal(1,num_poles) ;
430 new TColStd_HArray1OfReal(1,num_spans+1) ;
432 new TColStd_HArray1OfInteger(1,num_spans+1) ;
433 if (tgt_theta_flag) {
436 CosNumeratorPtr->SetValue(1,Cos(UFirst)) ;
437 SinNumeratorPtr->SetValue(1,Sin(UFirst)) ;
438 DenominatorPtr ->SetValue(1,1.0e0) ;
439 KnotsPtr->SetValue(1,param) ;
440 MultsPtr->SetValue(1,Degree + 1) ;
441 direct = Cos(alpha) ;
442 inverse = 1.0e0 / direct ;
443 for (ii = 1 ; ii <= num_spans ; ii++ ) {
444 CosNumeratorPtr->SetValue(2 * ii, inverse * Cos(param + alpha)) ;
445 SinNumeratorPtr->SetValue(2 * ii, inverse * Sin(param + alpha)) ;
446 DenominatorPtr->SetValue(2 * ii, direct) ;
447 CosNumeratorPtr->SetValue(2 * ii + 1, Cos(param + 2 * alpha)) ;
448 SinNumeratorPtr->SetValue(2 * ii + 1, Sin(param + 2 * alpha)) ;
449 DenominatorPtr->SetValue(2 * ii + 1, 1.0e0) ;
450 KnotsPtr->SetValue(ii + 1, param + 2 * alpha) ;
451 MultsPtr->SetValue(ii + 1, 2) ;
454 MultsPtr->SetValue(num_spans + 1, Degree + 1) ;
456 else if (Parameterisation != Convert_Polynomial) {
457 alpha = ULast - UFirst ;
459 beta = ULast + UFirst ;
461 cos_beta = Cos(beta) ;
462 sin_beta = Sin(beta) ;
463 num_flat_knots = num_poles + order ;
467 TColStd_Array1OfReal flat_knots(1, num_flat_knots) ;
470 TColgp_Array1OfPnt2d temp_poles(1,num_temp_poles) ;
471 TColStd_Array1OfReal temp_knots(1,num_temp_knots) ;
472 TColStd_Array1OfInteger temp_mults(1,num_temp_knots) ;
474 for (ii = 1 ; ii <= order ; ii++) {
475 flat_knots(ii) = -alpha ;
476 flat_knots(ii + num_poles) = alpha ;
478 KnotsPtr->SetValue(1,UFirst) ;
479 KnotsPtr->SetValue(num_knots, ULast) ;
480 MultsPtr->SetValue(1,order) ;
481 MultsPtr->SetValue(num_knots,order) ;
483 switch (Parameterisation) {
484 case Convert_QuasiAngular:
486 // we code here in temp_poles(xx).Coord(1) the following function V(t)
487 // and in temp_poles(xx).Coord(2) the function U(t)
493 // c = --- + b = q_param
497 // gamma + ------ - tang gamma
499 // b =------------------------------ = p_param
501 // gamma (tang gamma - gamma)
503 // with gamma = alpha / 2
507 alpha_2 = alpha * 0.5e0 ;
508 p_param = - 1.0e0 / (alpha_2 * alpha_2) ;
510 if (alpha_2 < M_PI * 0.5e0) {
511 tan_alpha_2 = Tan(alpha_2) ;
512 value1 = 3.0e0 * (tan_alpha_2 - alpha_2) ;
513 value1 = alpha_2 / value1 ;
516 q_param = (1.0e0 / 3.0e0) + p_param ;
520 temp_poles(1).SetCoord(1,0.0e0);
521 temp_poles(2).SetCoord(1,1.0e0);
522 temp_poles(3).SetCoord(1,0.0e0) ;
523 temp_poles(4).SetCoord(1,q_param) ;
525 temp_poles(1).SetCoord(2, 1.0e0) ;
526 temp_poles(2).SetCoord(2, 0.0e0) ;
527 temp_poles(3).SetCoord(2, p_param) ;
528 temp_poles(4).SetCoord(2, 0.0e0);
529 EvaluatorPtr = &CosAndSinQuasiAngular ;
531 case Convert_RationalC1:
532 for (ii = order + 1 ; ii <= num_poles ; ii++) {
533 flat_knots(ii) = 0.0e0 ;
535 KnotsPtr->SetValue(2,UFirst + alpha) ;
536 MultsPtr->SetValue(2,Degree -1) ;
538 alpha_2 = alpha * 0.5e0 ;
539 alpha_4 = alpha * 0.25e0 ;
540 tan_alpha_2 = Tan(alpha_2) ;
542 for (ii = 1 ; ii <= 2 ; ii++) {
543 temp_poles(1+ ii).SetCoord(2,1.0e0 + alpha_4 * tan_alpha_2) ;
544 temp_poles(jj).SetCoord(2,1.e0) ;
547 temp_poles(1).SetCoord(1,-tan_alpha_2) ;
548 temp_poles(2).SetCoord(1,alpha_4 - tan_alpha_2) ;
549 temp_poles(3).SetCoord(1,-alpha_4 + tan_alpha_2) ;
550 temp_poles(4).SetCoord(1,tan_alpha_2) ;
551 temp_knots(1) = -alpha ;
552 temp_knots(2) = 0.0e0 ;
553 temp_knots(3) = alpha ;
554 temp_mults(1) = temp_degree + 1;
556 temp_mults(3) = temp_degree + 1;
558 EvaluatorPtr = &CosAndSinRationalC1 ;
563 AlgorithmicCosAndSin(Degree,
570 CosNumeratorPtr->ChangeArray1(),
571 SinNumeratorPtr->ChangeArray1(),
572 DenominatorPtr->ChangeArray1()) ;
574 for (ii = 1 ; ii <= num_poles ; ii++) {
575 value1 = cos_beta * CosNumeratorPtr->Value(ii) -
576 sin_beta * SinNumeratorPtr->Value(ii) ;
577 value2 = sin_beta * CosNumeratorPtr->Value(ii) +
578 cos_beta * SinNumeratorPtr->Value(ii) ;
579 CosNumeratorPtr->SetValue(ii,value1) ;
580 SinNumeratorPtr->SetValue(ii,value2) ;
583 else { // Convert_Polynomial
585 KnotsPtr->SetValue(1, 0.) ;
586 KnotsPtr->SetValue(num_knots, 1.);
587 MultsPtr->SetValue(1, num_poles);
588 MultsPtr->SetValue(num_knots, num_poles);
590 BuildPolynomialCosAndSin(UFirst,ULast,num_poles,
591 CosNumeratorPtr,SinNumeratorPtr,DenominatorPtr);
596 //=======================================================================
597 //function : BuildCosAndSin
599 //=======================================================================
601 void Convert_ConicToBSplineCurve::BuildCosAndSin(
602 const Convert_ParameterisationType Parameterisation,
603 Handle(TColStd_HArray1OfReal)& CosNumeratorPtr,
604 Handle(TColStd_HArray1OfReal)& SinNumeratorPtr,
605 Handle(TColStd_HArray1OfReal)& DenominatorPtr,
606 Standard_Integer& Degree,
607 Handle(TColStd_HArray1OfReal)& KnotsPtr,
608 Handle(TColStd_HArray1OfInteger)& MultsPtr) const
610 Standard_Real half_pi,
632 if (Parameterisation != Convert_TgtThetaOver2 &&
633 Parameterisation != Convert_RationalC1) {
634 Standard_ConstructionError::Raise() ;
636 Handle(TColStd_HArray1OfReal) temp_cos_ptr,
638 temp_denominator_ptr,
640 Handle(TColStd_HArray1OfInteger) temp_mults_ptr;
641 if (Parameterisation == Convert_TgtThetaOver2) {
642 BuildCosAndSin(Convert_TgtThetaOver2_3,
647 temp_denominator_ptr,
652 new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
654 new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
656 new TColStd_HArray1OfReal(1,temp_cos_ptr->Length() -1) ;
657 for (ii = temp_cos_ptr->Lower() ; ii <= temp_cos_ptr->Upper()-1 ; ii++) {
658 CosNumeratorPtr->SetValue(ii,temp_cos_ptr->Value(ii)) ;
659 SinNumeratorPtr->SetValue(ii,temp_sin_ptr->Value(ii)) ;
660 DenominatorPtr->SetValue(ii,temp_denominator_ptr->Value(ii)) ;
662 for (ii = MultsPtr->Lower() ; ii <= MultsPtr->Upper() ; ii++) {
663 MultsPtr->SetValue(ii, Degree) ;
666 else if (Parameterisation == Convert_RationalC1)
668 first_param = 0.0e0 ;
670 BuildCosAndSin(Convert_RationalC1,
675 temp_denominator_ptr,
684 num_flat_knots = (Degree -1) * num_knots + 2 * 2 ;
685 num_poles = num_flat_knots - order ;
686 num_periodic_poles = num_poles - 2 ;
687 TColStd_Array1OfReal flat_knots(1,num_flat_knots) ;
689 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
691 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
693 new TColStd_HArray1OfReal(1,num_periodic_poles) ;
695 half_pi = M_PI * 0.5e0 ;
697 for (jj = 1 ; jj <= 2 ; jj++) {
698 flat_knots(index) = - half_pi ;
701 for (ii = 1 ; ii <= num_knots ; ii++) {
702 for (jj = 1 ; jj <= Degree -1 ; jj++) {
703 flat_knots(index) = (ii-1) * half_pi ;
709 for (jj = 1 ; jj <= 2 ; jj++) {
710 flat_knots(index) = 2 * M_PI + half_pi ;
714 new TColStd_HArray1OfReal(1,num_knots) ;
716 new TColStd_HArray1OfInteger(1,num_knots) ;
717 for ( ii = 1 ; ii <= num_knots ; ii++) {
718 KnotsPtr->SetValue(ii, (ii-1) * half_pi) ;
719 MultsPtr->SetValue(ii, Degree-1) ;
723 TColStd_Array1OfReal parameters(1,num_poles) ;
724 TColgp_Array1OfPnt poles_array(1,num_poles) ;
725 TColStd_Array1OfInteger contact_order_array(1,num_poles) ;
726 BSplCLib::BuildSchoenbergPoints(Degree,
730 for (ii = parameters.Lower() ; ii <= parameters.Upper() ; ii++) {
731 param = parameters(ii) ;
740 temp_cos_ptr->Array1(),
741 temp_denominator_ptr->Array1(),
742 temp_knots_ptr->Array1(),
743 temp_mults_ptr->Array1(),
750 temp_sin_ptr->Array1(),
751 temp_denominator_ptr->Array1(),
752 temp_knots_ptr->Array1(),
753 temp_mults_ptr->Array1(),
759 temp_denominator_ptr->Array1(),
760 BSplCLib::NoWeights(),
761 temp_knots_ptr->Array1(),
762 temp_mults_ptr->Array1(),
764 contact_order_array(ii) = 0 ;
766 poles_array(ii).SetCoord(1,
767 value1 * value3 * inverse) ;
768 poles_array(ii).SetCoord(2,
769 value2 * value3 * inverse) ;
770 poles_array(ii).SetCoord(3,
773 BSplCLib::Interpolate(Degree,
778 pivot_index_problem) ;
779 for (ii = 1 ; ii <= num_periodic_poles ; ii++) {
780 inverse = 1.0e0 / poles_array(ii).Coord(3) ;
781 CosNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(1) * inverse ;
782 SinNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(2) * inverse ;
783 DenominatorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(3) ;