1 // Created on: 1995-01-17
2 // Created by: Laurent BOURESCHE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // xab : modified 15-Mar-95 : added BuildBSplMatrix,FactorBandedMatrix,
19 // EvalPolynomial : Horners method
21 #include <Standard_Stream.hxx>
23 #include <BSplCLib.hxx>
24 #include <gp_Mat2d.hxx>
26 #include <Standard_ConstructionError.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28 #include <TColStd_Array1OfInteger.hxx>
29 #include <TColStd_HArray1OfReal.hxx>
30 #include <TColStd_HArray1OfInteger.hxx>
32 #include <math_Matrix.hxx>
34 //=======================================================================
35 //struct : BSplCLib_DataContainer
36 //purpose: Auxiliary structure providing buffers for poles and knots used in
37 // evaluation of bspline (allocated in the stack)
38 //=======================================================================
40 struct BSplCLib_DataContainer
42 BSplCLib_DataContainer(Standard_Integer Degree)
44 (void)Degree; // avoid compiler warning
45 Standard_OutOfRange_Raise_if (Degree > BSplCLib::MaxDegree() ||
46 BSplCLib::MaxDegree() > 25,
47 "BSplCLib: bspline degree is greater than maximum supported");
50 Standard_Real poles[2*(25+1)];
51 Standard_Real knots[2*25];
52 Standard_Real ders[4];
55 // methods for 1 dimensional BSplines
57 //=======================================================================
58 //function : BuildEval
59 //purpose : builds the local array for evaluation
60 //=======================================================================
62 void BSplCLib::BuildEval(const Standard_Integer Degree,
63 const Standard_Integer Index,
64 const TColStd_Array1OfReal& Poles,
65 const TColStd_Array1OfReal& Weights,
68 Standard_Integer PLower = Poles.Lower();
69 Standard_Integer PUpper = Poles.Upper();
71 Standard_Integer ip = PLower + Index - 1;
72 Standard_Real w, *pole = &LP;
73 if (&Weights == NULL) {
75 for (i = 0; i <= Degree; i++) {
77 if (ip > PUpper) ip = PLower;
84 for (i = 0; i <= Degree; i++) {
86 if (ip > PUpper) ip = PLower;
87 pole[1] = w = Weights(ip);
88 pole[0] = Poles(ip) * w;
94 //=======================================================================
95 //function : PrepareEval
96 //purpose : stores data for Eval in the local arrays
97 // dc.poles and dc.knots
98 //=======================================================================
100 static void PrepareEval
102 Standard_Integer& index,
103 Standard_Integer& dim,
104 Standard_Boolean& rational,
105 const Standard_Integer Degree,
106 const Standard_Boolean Periodic,
107 const TColStd_Array1OfReal& Poles,
108 const TColStd_Array1OfReal& Weights,
109 const TColStd_Array1OfReal& Knots,
110 const TColStd_Array1OfInteger& Mults,
111 BSplCLib_DataContainer& dc)
114 BSplCLib::LocateParameter(Degree,Knots,Mults,u,Periodic,index,u);
117 BSplCLib::BuildKnots(Degree,index,Periodic,Knots,Mults,*dc.knots);
119 index -= Knots.Lower() + Degree;
121 index = BSplCLib::PoleIndex(Degree,index,Periodic,Mults);
123 // check truly rational
124 rational = (&Weights != NULL);
126 Standard_Integer WLower = Weights.Lower() + index;
127 rational = BSplCLib::IsRational(Weights, WLower, WLower + Degree);
133 BSplCLib::BuildEval(Degree, index, Poles, Weights , *dc.poles);
137 BSplCLib::BuildEval(Degree, index, Poles, BSplCLib::NoWeights(), *dc.poles);
141 //=======================================================================
144 //=======================================================================
147 (const Standard_Real U,
148 const Standard_Integer Index,
149 const Standard_Integer Degree,
150 const Standard_Boolean Periodic,
151 const TColStd_Array1OfReal& Poles,
152 const TColStd_Array1OfReal& Weights,
153 const TColStd_Array1OfReal& Knots,
154 const TColStd_Array1OfInteger& Mults,
157 Standard_Integer dim,index = Index;
159 Standard_Boolean rational;
160 BSplCLib_DataContainer dc(Degree);
161 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
162 BSplCLib::Eval(u,Degree,*dc.knots,dim,*dc.poles);
163 if (rational) P = dc.poles[0] / dc.poles[1];
164 else P = dc.poles[0];
167 //=======================================================================
170 //=======================================================================
173 (const Standard_Real U,
174 const Standard_Integer Index,
175 const Standard_Integer Degree,
176 const Standard_Boolean Periodic,
177 const TColStd_Array1OfReal& Poles,
178 const TColStd_Array1OfReal& Weights,
179 const TColStd_Array1OfReal& Knots,
180 const TColStd_Array1OfInteger& Mults,
184 Standard_Integer dim,index = Index;
186 Standard_Boolean rational;
187 BSplCLib_DataContainer dc(Degree);
188 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
189 BSplCLib::Bohm(u,Degree,1,*dc.knots,dim,*dc.poles);
190 Standard_Real *result = dc.poles;
192 PLib::RationalDerivative(Degree,1,1,*dc.poles,*dc.ders);
199 //=======================================================================
202 //=======================================================================
205 (const Standard_Real U,
206 const Standard_Integer Index,
207 const Standard_Integer Degree,
208 const Standard_Boolean Periodic,
209 const TColStd_Array1OfReal& Poles,
210 const TColStd_Array1OfReal& Weights,
211 const TColStd_Array1OfReal& Knots,
212 const TColStd_Array1OfInteger& Mults,
217 Standard_Integer dim,index = Index;
219 Standard_Boolean rational;
220 BSplCLib_DataContainer dc(Degree);
221 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
222 BSplCLib::Bohm(u,Degree,2,*dc.knots,dim,*dc.poles);
223 Standard_Real *result = dc.poles;
225 PLib::RationalDerivative(Degree,2,1,*dc.poles,*dc.ders);
230 if (!rational && (Degree < 2)) V2 = 0.;
234 //=======================================================================
237 //=======================================================================
240 (const Standard_Real U,
241 const Standard_Integer Index,
242 const Standard_Integer Degree,
243 const Standard_Boolean Periodic,
244 const TColStd_Array1OfReal& Poles,
245 const TColStd_Array1OfReal& Weights,
246 const TColStd_Array1OfReal& Knots,
247 const TColStd_Array1OfInteger& Mults,
253 Standard_Integer dim,index = Index;
255 Standard_Boolean rational;
256 BSplCLib_DataContainer dc(Degree);
257 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
258 BSplCLib::Bohm(u,Degree,3,*dc.knots,dim,*dc.poles);
259 Standard_Real *result = dc.poles;
261 PLib::RationalDerivative(Degree,3,1,*dc.poles,*dc.ders);
266 if (!rational && (Degree < 2)) V2 = 0.;
268 if (!rational && (Degree < 3)) V3 = 0.;
272 //=======================================================================
275 //=======================================================================
278 (const Standard_Real U,
279 const Standard_Integer N,
280 const Standard_Integer Index,
281 const Standard_Integer Degree,
282 const Standard_Boolean Periodic,
283 const TColStd_Array1OfReal& Poles,
284 const TColStd_Array1OfReal& Weights,
285 const TColStd_Array1OfReal& Knots,
286 const TColStd_Array1OfInteger& Mults,
289 Standard_Integer dim,index = Index;
291 Standard_Boolean rational;
292 BSplCLib_DataContainer dc(Degree);
293 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
294 BSplCLib::Bohm(u,Degree,N,*dc.knots,dim,*dc.poles);
297 PLib::RationalDerivative(Degree,N,1,*dc.poles,v,Standard_False);
301 if (N > Degree) VN = 0.;
302 else VN = dc.poles[N];
306 //=======================================================================
307 //function : Build BSpline Matrix
308 //purpose : Builds the Bspline Matrix
309 //=======================================================================
312 BSplCLib::BuildBSpMatrix(const TColStd_Array1OfReal& Parameters,
313 const TColStd_Array1OfInteger& ContactOrderArray,
314 const TColStd_Array1OfReal& FlatKnots,
315 const Standard_Integer Degree,
317 Standard_Integer& UpperBandWidth,
318 Standard_Integer& LowerBandWidth)
325 FirstNonZeroBsplineIndex,
330 math_Matrix BSplineBasis(1, MaxOrder,
334 UpperBandWidth = Degree ;
335 LowerBandWidth = Degree ;
336 BandWidth = UpperBandWidth + LowerBandWidth + 1 ;
337 if (Matrix.LowerRow() != Parameters.Lower() ||
338 Matrix.UpperRow() != Parameters.Upper() ||
339 Matrix.LowerCol() != 1 ||
340 Matrix.UpperCol() != BandWidth) {
345 for (ii = Parameters.Lower() ; ii <= Parameters.Upper() ; ii++) {
347 BSplCLib::EvalBsplineBasis(1,
348 ContactOrderArray(ii),
353 FirstNonZeroBsplineIndex,
355 if (ErrorCode != 0) {
359 Index = LowerBandWidth + 1 + FirstNonZeroBsplineIndex - ii ;
361 for (jj = 1 ; jj < Index ; jj++) {
362 Matrix.Value(ii,jj) = 0.0e0 ;
365 for (jj = 1 ; jj <= Order ; jj++) {
366 Matrix.Value(ii,Index) = BSplineBasis(ContactOrderArray(ii) + 1, jj) ;
370 for (jj = Index ; jj <= BandWidth ; jj++) {
371 Matrix.Value(ii,jj) = 0.0e0 ;
375 return (ReturnCode) ;
378 //=======================================================================
379 //function : Makes LU decompositiomn without Pivoting
380 //purpose : Builds the Bspline Matrix
381 //=======================================================================
384 BSplCLib::FactorBandedMatrix(math_Matrix& Matrix,
385 const Standard_Integer UpperBandWidth,
386 const Standard_Integer LowerBandWidth,
387 Standard_Integer& PivotIndexProblem)
396 BandWidth = UpperBandWidth + LowerBandWidth + 1 ;
398 Standard_Real Inverse ;
399 PivotIndexProblem = 0 ;
401 for (ii = Matrix.LowerRow() + 1 ; ii <= Matrix.UpperRow() ; ii++) {
402 MinIndex = ( LowerBandWidth - ii + 2 >= 1 ? LowerBandWidth - ii + 2 : 1) ;
404 for (jj = MinIndex ; jj <= LowerBandWidth ; jj++) {
405 Index = ii - LowerBandWidth + jj - 1 ;
406 Inverse = Matrix(Index ,LowerBandWidth + 1) ;
407 if (Abs(Inverse) > RealSmall()) {
408 Inverse = -1.0e0/Inverse ;
412 PivotIndexProblem = Index ;
415 Matrix(ii,jj) = Matrix(ii,jj) * Inverse ;
416 MaxIndex = BandWidth + Index - ii ;
418 for (kk = jj + 1 ; kk <= MaxIndex ; kk++) {
419 Matrix(ii,kk) += Matrix(ii,jj) * Matrix(Index, kk + ii - Index) ;
424 return (ReturnCode) ;
427 //=======================================================================
428 //function : Build BSpline Matrix
429 //purpose : Builds the Bspline Matrix
430 //=======================================================================
433 BSplCLib::EvalBsplineBasis
434 //(const Standard_Integer Side, // = 1 rigth side, -1 left side
435 (const Standard_Integer , // = 1 rigth side, -1 left side
436 const Standard_Integer DerivativeRequest,
437 const Standard_Integer Order,
438 const TColStd_Array1OfReal& FlatKnots,
439 const Standard_Real Parameter,
440 Standard_Integer& FirstNonZeroBsplineIndex,
441 math_Matrix& BsplineBasis,
442 Standard_Boolean isPeriodic)
444 // the matrix must have at least DerivativeRequest + 1
445 // row and Order columns
446 // the result are stored in the following way in
447 // the Bspline matrix
448 // Let i be the FirstNonZeroBsplineIndex and
449 // t be the parameter value, k the order of the
450 // knot vector, r the DerivativeRequest :
476 Standard_Real NewParameter,
481 // , *FlatKnotsArray ;
484 FirstNonZeroBsplineIndex = 0 ;
485 LocalRequest = DerivativeRequest ;
486 if (DerivativeRequest >= Order) {
487 LocalRequest = Order - 1 ;
490 if (BsplineBasis.LowerCol() != 1 ||
491 BsplineBasis.UpperCol() < Order ||
492 BsplineBasis.LowerRow() != 1 ||
493 BsplineBasis.UpperRow() <= LocalRequest) {
497 NumPoles = FlatKnots.Upper() - FlatKnots.Lower() + 1 - Order ;
498 BSplCLib::LocateParameter(Order - 1,
507 FirstNonZeroBsplineIndex = ii - Order + 1 ;
509 BsplineBasis(1,1) = 1.0e0 ;
510 LocalRequest = DerivativeRequest ;
511 if (DerivativeRequest >= Order) {
512 LocalRequest = Order - 1 ;
515 for (qq = 2 ; qq <= Order - LocalRequest ; qq++) {
516 BsplineBasis(1,qq) = 0.0e0 ;
518 for (pp = 1 ; pp <= qq - 1 ; pp++) {
520 // this should be always invertible if ii is correctly computed
522 Factor = (Parameter - FlatKnots(ii - qq + pp + 1))
523 / (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1)) ;
524 Saved = Factor * BsplineBasis(1,pp) ;
525 BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
526 BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
527 BsplineBasis(1,qq) = Saved ;
531 for (qq = Order - LocalRequest + 1 ; qq <= Order ; qq++) {
533 for (pp = 1 ; pp <= qq - 1 ; pp++) {
534 BsplineBasis(Order - qq + 2,pp) = BsplineBasis(1,pp) ;
536 BsplineBasis(1,qq) = 0.0e0 ;
538 for (ss = Order - LocalRequest + 1 ; ss <= qq ; ss++) {
539 BsplineBasis(Order - ss + 2,qq) = 0.0e0 ;
542 for (pp = 1 ; pp <= qq - 1 ; pp++) {
543 Inverse = 1.0e0 / (FlatKnots(ii + pp) - FlatKnots(ii - qq + pp + 1)) ;
544 Factor = (Parameter - FlatKnots(ii - qq + pp + 1)) * Inverse ;
545 Saved = Factor * BsplineBasis(1,pp) ;
546 BsplineBasis(1,pp) *= (1.0e0 - Factor) ;
547 BsplineBasis(1,pp) += BsplineBasis(1,qq) ;
548 BsplineBasis(1,qq) = Saved ;
549 LocalInverse = (Standard_Real) (qq - 1) * Inverse ;
551 for (ss = Order - LocalRequest + 1 ; ss <= qq ; ss++) {
552 Saved = LocalInverse * BsplineBasis(Order - ss + 2, pp) ;
553 BsplineBasis(Order - ss + 2, pp) *= - LocalInverse ;
554 BsplineBasis(Order - ss + 2, pp) += BsplineBasis(Order - ss + 2,qq) ;
555 BsplineBasis(Order - ss + 2,qq) = Saved ;
560 return (ReturnCode) ;
563 //=======================================================================
564 //function : MovePointAndTangent
566 //=======================================================================
568 void BSplCLib::MovePointAndTangent(const Standard_Real U,
569 const Standard_Integer ArrayDimension,
570 Standard_Real &Delta,
571 Standard_Real &DeltaDerivatives,
572 const Standard_Real Tolerance,
573 const Standard_Integer Degree,
574 const Standard_Boolean Rational,
575 const Standard_Integer StartingCondition,
576 const Standard_Integer EndingCondition,
577 Standard_Real& Poles,
578 const TColStd_Array1OfReal& Weights,
579 const TColStd_Array1OfReal& FlatKnots,
580 Standard_Real& NewPoles,
581 Standard_Integer& ErrorStatus)
583 Standard_Integer num_poles,
597 Standard_Real new_parameter,
609 weights_array = NULL ;
611 weights_array = (Standard_Real *) &Weights(Weights.Lower()) ;
614 poles_array = &Poles ;
615 new_poles_array = &NewPoles ;
616 delta_array = &Delta ;
617 derivatives_array = &DeltaDerivatives ;
619 num_knots = FlatKnots.Length() ;
620 num_poles = num_knots - order ;
621 conditions = StartingCondition + EndingCondition + 4 ;
623 // check validity of input data
625 if (StartingCondition >= -1 &&
626 StartingCondition <= Degree &&
627 EndingCondition >= -1 &&
628 EndingCondition <= Degree &&
629 conditions <= num_poles) {
631 // check the parameter is within bounds
633 start_index = FlatKnots.Lower() + Degree ;
634 end_index = FlatKnots.Upper() - Degree ;
636 // check if there is enough room to move the poles
639 if (StartingCondition == -1) {
640 conditions = conditions && (FlatKnots(start_index) <= U) ;
643 conditions = conditions && (FlatKnots(start_index) + Tolerance < U) ;
645 if (EndingCondition == -1) {
646 conditions = conditions && (FlatKnots(end_index) >= U) ;
649 conditions = conditions && (FlatKnots(end_index) - Tolerance > U) ;
654 // build 2 auxialiary functions
656 TColStd_Array1OfReal schoenberg_points(1,num_poles) ;
657 TColStd_Array1OfReal first_function (1,num_poles) ;
658 TColStd_Array1OfReal second_function (1,num_poles) ;
660 BuildSchoenbergPoints(Degree,
663 start_index = StartingCondition + 2 ;
664 end_index = num_poles - EndingCondition - 1 ;
665 LocateParameter(schoenberg_points,
674 if (index == start_index) {
675 other_index = index + 1 ;
677 else if (index == end_index) {
678 other_index = index -1 ;
680 else if (U - FlatKnots(index) < FlatKnots(index + 1) - U ) {
681 other_index = index - 1 ;
684 other_index = index + 1 ;
688 start_num_poles = StartingCondition + 2 ;
689 end_num_poles = num_poles - EndingCondition - 1 ;
690 if (start_num_poles == 1) {
691 start_value = schoenberg_points(num_poles) - schoenberg_points(1) ;
692 start_value = schoenberg_points(1) - start_value ;
695 start_value = schoenberg_points(start_num_poles - 1) ;
697 if (end_num_poles == num_poles) {
698 end_value = schoenberg_points(num_poles) - schoenberg_points(1) ;
699 end_value = schoenberg_points(num_poles) + end_value ;
702 end_value = schoenberg_points(end_num_poles + 1) ;
705 for (ii = 1 ; ii < start_num_poles ; ii++) {
706 first_function(ii) = 0.e0 ;
707 second_function(ii) = 0.0e0 ;
710 for (ii = end_num_poles + 1 ; ii <= num_poles ; ii++) {
711 first_function(ii) = 0.e0 ;
712 second_function(ii) = 0.0e0 ;
714 divide = 1.0e0 / (schoenberg_points(index) - start_value) ;
716 for (ii = start_num_poles ; ii <= index ; ii++) {
717 value = schoenberg_points(ii) - start_value ;
719 first_function(ii) = 1.0e0 ;
721 for (jj = 0 ; jj < type ; jj++) {
722 first_function(ii) *= value ;
725 divide = 1.0e0 /(end_value - schoenberg_points(index)) ;
727 for (ii = index ; ii <= end_num_poles ; ii++) {
728 value = end_value - schoenberg_points(ii) ;
730 first_function(ii) = 1.0e0 ;
732 for (jj = 0 ; jj < type ; jj++) {
733 first_function(ii) *= value ;
737 divide = 1.0e0 / (schoenberg_points(other_index) - start_value) ;
739 for (ii = start_num_poles ; ii <= other_index ; ii++) {
740 value = schoenberg_points(ii) - start_value ;
742 second_function(ii) = 1.0e0 ;
744 for (jj = 0 ; jj < type ; jj++) {
745 second_function(ii) *= value ;
748 divide = 1.0e0/( end_value - schoenberg_points(other_index)) ;
750 for (ii = other_index ; ii <= end_num_poles ; ii++) {
751 value = end_value - schoenberg_points(ii) ;
753 second_function(ii) = 1.0e0 ;
755 for (jj = 0 ; jj < type ; jj++) {
756 second_function(ii) *= value ;
761 // compute the point and derivatives of both functions
763 Standard_Real results[2][2],
764 weights_results[2][2];
765 Standard_Integer extrap_mode[2],
766 derivative_request = 1,
768 Standard_Boolean periodic_flag = Standard_False ;
770 extrap_mode[0] = Degree ;
771 extrap_mode[1] = Degree ;
774 // evaluate in homogenised form
786 weights_results[0][0]) ;
798 weights_results[1][0]) ;
800 // compute the rational derivatives values
803 for (ii = 0 ; ii < 2 ; ii++) {
804 PLib::RationalDerivatives(1,
807 weights_results[ii][0],
834 for (ii = 0 ; ii < 2 ; ii++) {
836 for (jj = 0 ; jj < 2 ; jj++) {
837 a_matrix.SetValue(ii+1,jj+1,results[ii][jj]) ;
841 TColStd_Array1OfReal the_a_vector(0,ArrayDimension-1) ;
842 TColStd_Array1OfReal the_b_vector(0,ArrayDimension-1) ;
844 for( ii = 0 ; ii < ArrayDimension ; ii++) {
846 a_matrix.Value(1,1) * delta_array[ii] +
847 a_matrix.Value(2,1) * derivatives_array[ii] ;
849 a_matrix.Value(1,2) * delta_array[ii] +
850 a_matrix.Value(2,2) * derivatives_array[ii] ;
854 for (ii = 0 ; ii < num_poles ; ii++) {
856 for (jj = 0 ; jj < ArrayDimension ; jj++) {
857 new_poles_array[index] = poles_array[index] ;
858 new_poles_array[index] +=
859 first_function(ii+1) * the_a_vector(jj) ;
860 new_poles_array[index] +=
861 second_function(ii+1) * the_b_vector(jj) ;
875 //=======================================================================
876 //function : FunctionMultiply
878 //=======================================================================
880 void BSplCLib::FunctionMultiply
881 (const BSplCLib_EvaluatorFunction & FunctionPtr,
882 const Standard_Integer BSplineDegree,
883 const TColStd_Array1OfReal & BSplineFlatKnots,
884 const Standard_Integer PolesDimension,
885 Standard_Real & Poles,
886 const TColStd_Array1OfReal & FlatKnots,
887 const Standard_Integer NewDegree,
888 Standard_Real & NewPoles,
889 Standard_Integer & Status)
894 Standard_Integer extrap_mode[2],
897 derivative_request = 0 ;
898 Standard_Boolean periodic_flag = Standard_False ;
899 Standard_Real result,
902 *array_of_new_poles ;
904 array_of_poles = (Standard_Real *) &NewPoles ;
906 extrap_mode[1] = BSplineDegree ;
908 FlatKnots.Length() - NewDegree - 1 ;
909 start_end[0] = FlatKnots(NewDegree+1) ;
910 start_end[1] = FlatKnots(num_new_poles+1) ;
911 TColStd_Array1OfReal parameters(1,num_new_poles) ;
912 TColStd_Array1OfInteger contact_order_array(1,num_new_poles) ;
913 TColStd_Array1OfReal new_poles_array(1, num_new_poles * PolesDimension) ;
916 (Standard_Real *) &new_poles_array(1) ;
917 BuildSchoenbergPoints(NewDegree,
921 // on recadre sur les bornes
923 if (parameters(1) < start_end[0]) {
924 parameters(1) = start_end[0] ;
926 if (parameters(num_new_poles) > start_end[1]) {
927 parameters(num_new_poles) = start_end[1] ;
931 for (ii = 1 ; ii <= num_new_poles ; ii++) {
932 contact_order_array(ii) = 0 ;
933 FunctionPtr.Evaluate (contact_order_array(ii),
951 array_of_new_poles[index]) ;
953 for (jj = 0 ; jj < PolesDimension ; jj++) {
954 array_of_new_poles[index] *= result ;
958 Interpolate(NewDegree,
963 array_of_new_poles[0],
966 for (ii = 0 ; ii < num_new_poles * PolesDimension ; ii++) {
967 array_of_poles[ii] = array_of_new_poles[ii] ;
974 //=======================================================================
975 // function : FunctionMultiply
977 //=======================================================================
979 void BSplCLib::FunctionReparameterise
980 (const BSplCLib_EvaluatorFunction & FunctionPtr,
981 const Standard_Integer BSplineDegree,
982 const TColStd_Array1OfReal & BSplineFlatKnots,
983 const Standard_Integer PolesDimension,
984 Standard_Real & Poles,
985 const TColStd_Array1OfReal & FlatKnots,
986 const Standard_Integer NewDegree,
987 Standard_Real & NewPoles,
988 Standard_Integer & Status)
993 Standard_Integer extrap_mode[2],
996 derivative_request = 0 ;
997 Standard_Boolean periodic_flag = Standard_False ;
998 Standard_Real result,
1001 *array_of_new_poles ;
1003 array_of_poles = (Standard_Real *) &NewPoles ;
1005 extrap_mode[1] = BSplineDegree ;
1007 FlatKnots.Length() - NewDegree - 1 ;
1008 start_end[0] = FlatKnots(NewDegree+1) ;
1009 start_end[1] = FlatKnots(num_new_poles+1) ;
1010 TColStd_Array1OfReal parameters(1,num_new_poles) ;
1011 TColStd_Array1OfInteger contact_order_array(1,num_new_poles) ;
1012 TColStd_Array1OfReal new_poles_array(1, num_new_poles * PolesDimension) ;
1014 array_of_new_poles =
1015 (Standard_Real *) &new_poles_array(1) ;
1016 BuildSchoenbergPoints(NewDegree,
1021 for (ii = 1 ; ii <= num_new_poles ; ii++) {
1022 contact_order_array(ii) = 0 ;
1023 FunctionPtr.Evaluate (contact_order_array(ii),
1041 array_of_new_poles[index]) ;
1042 index += PolesDimension ;
1044 Interpolate(NewDegree,
1047 contact_order_array,
1049 array_of_new_poles[0],
1052 for (ii = 0 ; ii < num_new_poles * PolesDimension ; ii++) {
1053 array_of_poles[ii] = array_of_new_poles[ii] ;
1060 //=======================================================================
1061 //function : FunctionMultiply
1063 //=======================================================================
1065 void BSplCLib::FunctionMultiply
1066 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1067 const Standard_Integer BSplineDegree,
1068 const TColStd_Array1OfReal & BSplineFlatKnots,
1069 const TColStd_Array1OfReal & Poles,
1070 const TColStd_Array1OfReal & FlatKnots,
1071 const Standard_Integer NewDegree,
1072 TColStd_Array1OfReal & NewPoles,
1073 Standard_Integer & Status)
1075 Standard_Integer num_bspline_poles =
1076 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1077 Standard_Integer num_new_poles =
1078 FlatKnots.Length() - NewDegree - 1 ;
1080 if (Poles.Length() != num_bspline_poles ||
1081 NewPoles.Length() != num_new_poles) {
1082 Standard_ConstructionError::Raise();
1084 Standard_Real * array_of_poles =
1085 (Standard_Real *) &Poles(Poles.Lower()) ;
1086 Standard_Real * array_of_new_poles =
1087 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1088 BSplCLib::FunctionMultiply(FunctionPtr,
1095 array_of_new_poles[0],
1099 //=======================================================================
1100 //function : FunctionReparameterise
1102 //=======================================================================
1104 void BSplCLib::FunctionReparameterise
1105 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1106 const Standard_Integer BSplineDegree,
1107 const TColStd_Array1OfReal & BSplineFlatKnots,
1108 const TColStd_Array1OfReal & Poles,
1109 const TColStd_Array1OfReal & FlatKnots,
1110 const Standard_Integer NewDegree,
1111 TColStd_Array1OfReal & NewPoles,
1112 Standard_Integer & Status)
1114 Standard_Integer num_bspline_poles =
1115 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1116 Standard_Integer num_new_poles =
1117 FlatKnots.Length() - NewDegree - 1 ;
1119 if (Poles.Length() != num_bspline_poles ||
1120 NewPoles.Length() != num_new_poles) {
1121 Standard_ConstructionError::Raise();
1123 Standard_Real * array_of_poles =
1124 (Standard_Real *) &Poles(Poles.Lower()) ;
1125 Standard_Real * array_of_new_poles =
1126 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1127 BSplCLib::FunctionReparameterise(
1135 array_of_new_poles[0],
1139 //=======================================================================
1140 //function : MergeBSplineKnots
1142 //=======================================================================
1143 void BSplCLib::MergeBSplineKnots
1144 (const Standard_Real Tolerance,
1145 const Standard_Real StartValue,
1146 const Standard_Real EndValue,
1147 const Standard_Integer Degree1,
1148 const TColStd_Array1OfReal & Knots1,
1149 const TColStd_Array1OfInteger & Mults1,
1150 const Standard_Integer Degree2,
1151 const TColStd_Array1OfReal & Knots2,
1152 const TColStd_Array1OfInteger & Mults2,
1153 Standard_Integer & NumPoles,
1154 Handle(TColStd_HArray1OfReal) & NewKnots,
1155 Handle(TColStd_HArray1OfInteger) & NewMults)
1157 Standard_Integer ii,
1164 if (StartValue < EndValue - Tolerance) {
1165 TColStd_Array1OfReal knots1(1,Knots1.Length()) ;
1166 TColStd_Array1OfReal knots2(1,Knots2.Length()) ;
1167 degree = Degree1 + Degree2 ;
1170 for (ii = Knots1.Lower() ; ii <= Knots1.Upper() ; ii++) {
1171 knots1(index) = Knots1(ii) ;
1176 for (ii = Knots2.Lower() ; ii <= Knots2.Upper() ; ii++) {
1177 knots2(index) = Knots2(ii) ;
1180 BSplCLib::Reparametrize(StartValue,
1184 BSplCLib::Reparametrize(StartValue,
1190 for (ii = 1 ; ii <= knots1.Length() ; ii++) {
1192 while (jj <= knots2.Length() && knots2(jj) <= knots1(ii) - Tolerance) {
1197 while (jj <= knots2.Length() && knots2(jj) <= knots1(ii) + Tolerance) {
1203 new TColStd_HArray1OfReal(1,num_knots) ;
1205 new TColStd_HArray1OfInteger(1,num_knots) ;
1209 for (ii = 1 ; ii <= knots1.Length() ; ii++) {
1211 while (jj <= knots2.Length() && knots2(jj) <= knots1(ii) - Tolerance) {
1212 NewKnots->ChangeArray1()(num_knots) = knots2(jj) ;
1213 NewMults->ChangeArray1()(num_knots) = Mults2(jj) + Degree1 ;
1217 set_mults_flag = 0 ;
1219 while (jj <= knots2.Length() && knots2(jj) <= knots1(ii) + Tolerance) {
1220 continuity = Min(Degree1 - Mults1(ii), Degree2 - Mults2(jj)) ;
1221 set_mults_flag = 1 ;
1222 NewMults->ChangeArray1()(num_knots) = degree - continuity ;
1226 NewKnots->ChangeArray1()(num_knots) = knots1(ii) ;
1227 if (! set_mults_flag) {
1228 NewMults->ChangeArray1()(num_knots) = Mults1(ii) + Degree2 ;
1233 NewMults->ChangeArray1()(1) = degree + 1 ;
1234 NewMults->ChangeArray1()(num_knots) = degree + 1 ;
1237 for (ii = 1 ; ii <= num_knots ; ii++) {
1238 index += NewMults->Value(ii) ;
1240 NumPoles = index - degree - 1 ;