1 // xab : modified 15-Mar-94 added EvalBSplineMatrix, FactorBandedMatrix, SolveBandedSystem
2 // Eval, BuildCache, cacheD0, cacheD1, cacheD2, cacheD3, LocalMatrix,
3 // EvalPolynomial, RationalDerivatives.
4 // xab : 22-Mar-94 : fixed rational problem in BuildCache
5 // xab : 12-Mar-96 : added MovePointAndTangent
7 #include <TColStd_Array1OfInteger.hxx>
8 #include <TColStd_Array1OfReal.hxx>
9 #include <gp_Vec2d.hxx>
10 #include <Standard_ConstructionError.hxx>
12 #include <math_Matrix.hxx>
14 #define No_Standard_RangeError
15 #define No_Standard_OutOfRange
17 //=======================================================================
18 //struct : BSplCLib_DataContainer
19 //purpose: Auxiliary structure providing buffers for poles and knots used in
20 // evaluation of bspline (allocated in the stack)
21 //=======================================================================
23 struct BSplCLib_DataContainer
25 BSplCLib_DataContainer(Standard_Integer Degree)
27 if ( Degree > BSplCLib::MaxDegree() || BSplCLib::MaxDegree() > 25 )
28 Standard_OutOfRange::Raise ("BSplCLib: bspline degree is greater than maximum supported");
31 Standard_Real poles[(25+1)*(Dimension_gen+1)];
32 Standard_Real knots[2*25];
33 Standard_Real ders[Dimension_gen*4];
36 //=======================================================================
39 //=======================================================================
41 void BSplCLib::Reverse(Array1OfPoints& Poles,
42 const Standard_Integer L)
44 Standard_Integer i, l = L;
45 l = Poles.Lower() + (l-Poles.Lower()) % (Poles.Upper()-Poles.Lower()+1);
47 Array1OfPoints temp(0,Poles.Length()-1);
49 for (i = Poles.Lower(); i <= l; i++)
52 for (i = l+1; i <= Poles.Upper(); i++)
53 temp(l-Poles.Lower()+Poles.Upper()-i+1) = Poles(i);
55 for (i = Poles.Lower(); i <= Poles.Upper(); i++)
56 Poles(i) = temp(i-Poles.Lower());
60 // CURVES MODIFICATIONS
63 //=======================================================================
64 //function : RemoveKnot
66 //=======================================================================
68 Standard_Boolean BSplCLib::RemoveKnot
69 (const Standard_Integer Index,
70 const Standard_Integer Mult,
71 const Standard_Integer Degree,
72 const Standard_Boolean Periodic,
73 const Array1OfPoints& Poles,
74 const TColStd_Array1OfReal& Weights,
75 const TColStd_Array1OfReal& Knots,
76 const TColStd_Array1OfInteger& Mults,
77 Array1OfPoints& NewPoles,
78 TColStd_Array1OfReal& NewWeights,
79 TColStd_Array1OfReal& NewKnots,
80 TColStd_Array1OfInteger& NewMults,
81 const Standard_Real Tolerance)
83 Standard_Boolean rational = &Weights != NULL;
88 TColStd_Array1OfReal poles(1,dim*Poles.Length());
89 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
91 if (rational) PLib::SetPoles(Poles,Weights,poles);
92 else PLib::SetPoles(Poles,poles);
94 if (!RemoveKnot(Index,Mult,Degree,Periodic,dim,
95 poles,Knots,Mults,newpoles,NewKnots,NewMults,Tolerance))
96 return Standard_False;
98 if (rational) PLib::GetPoles(newpoles,NewPoles,NewWeights);
99 else PLib::GetPoles(newpoles,NewPoles);
100 return Standard_True;
103 //=======================================================================
104 //function : InsertKnots
105 //purpose : insert an array of knots and multiplicities
106 //=======================================================================
108 void BSplCLib::InsertKnots
109 (const Standard_Integer Degree,
110 const Standard_Boolean Periodic,
111 const Array1OfPoints& Poles,
112 const TColStd_Array1OfReal& Weights,
113 const TColStd_Array1OfReal& Knots,
114 const TColStd_Array1OfInteger& Mults,
115 const TColStd_Array1OfReal& AddKnots,
116 const TColStd_Array1OfInteger& AddMults,
117 Array1OfPoints& NewPoles,
118 TColStd_Array1OfReal& NewWeights,
119 TColStd_Array1OfReal& NewKnots,
120 TColStd_Array1OfInteger& NewMults,
121 const Standard_Real Epsilon,
122 const Standard_Boolean Add)
124 Standard_Boolean rational = &Weights != NULL;
125 Standard_Integer dim;
129 TColStd_Array1OfReal poles(1,dim*Poles.Length());
130 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
132 if (rational) PLib::SetPoles(Poles,Weights,poles);
133 else PLib::SetPoles(Poles,poles);
135 InsertKnots(Degree,Periodic,dim,poles,Knots,Mults,
136 AddKnots,AddMults,newpoles,NewKnots,NewMults,Epsilon,Add);
138 if (rational) PLib::GetPoles(newpoles,NewPoles,NewWeights);
139 else PLib::GetPoles(newpoles,NewPoles);
142 //=======================================================================
143 //function : InsertKnot
145 //=======================================================================
147 void BSplCLib::InsertKnot(const Standard_Integer ,
148 const Standard_Real U,
149 const Standard_Integer UMult,
150 const Standard_Integer Degree,
151 const Standard_Boolean Periodic,
152 const Array1OfPoints& Poles,
153 const TColStd_Array1OfReal& Weights,
154 const TColStd_Array1OfReal& Knots,
155 const TColStd_Array1OfInteger& Mults,
156 Array1OfPoints& NewPoles,
157 TColStd_Array1OfReal& NewWeights)
159 TColStd_Array1OfReal k(1,1);
161 TColStd_Array1OfInteger m(1,1);
163 TColStd_Array1OfReal nk(1,Knots.Length()+1);
164 TColStd_Array1OfInteger nm(1,Knots.Length()+1);
165 InsertKnots(Degree,Periodic,Poles,Weights,Knots,Mults,
166 k,m,NewPoles,NewWeights,nk,nm,Epsilon(U));
169 //=======================================================================
170 //function : RaiseMultiplicity
172 //=======================================================================
174 void BSplCLib::RaiseMultiplicity(const Standard_Integer KnotIndex,
175 const Standard_Integer Mult,
176 const Standard_Integer Degree,
177 const Standard_Boolean Periodic,
178 const Array1OfPoints& Poles,
179 const TColStd_Array1OfReal& Weights,
180 const TColStd_Array1OfReal& Knots,
181 const TColStd_Array1OfInteger& Mults,
182 Array1OfPoints& NewPoles,
183 TColStd_Array1OfReal& NewWeights)
185 TColStd_Array1OfReal k(1,1);
186 k(1) = Knots(KnotIndex);
187 TColStd_Array1OfInteger m(1,1);
188 m(1) = Mult - Mults(KnotIndex);
189 TColStd_Array1OfReal nk(1,Knots.Length());
190 TColStd_Array1OfInteger nm(1,Knots.Length());
191 InsertKnots(Degree,Periodic,Poles,Weights,Knots,Mults,
192 k,m,NewPoles,NewWeights,nk,nm,Epsilon(k(1)));
195 //=======================================================================
196 //function : IncreaseDegree
198 //=======================================================================
200 void BSplCLib::IncreaseDegree
201 (const Standard_Integer Degree,
202 const Standard_Integer NewDegree,
203 const Standard_Boolean Periodic,
204 const Array1OfPoints& Poles,
205 const TColStd_Array1OfReal& Weights,
206 const TColStd_Array1OfReal& Knots,
207 const TColStd_Array1OfInteger& Mults,
208 Array1OfPoints& NewPoles,
209 TColStd_Array1OfReal& NewWeights,
210 TColStd_Array1OfReal& NewKnots,
211 TColStd_Array1OfInteger& NewMults)
213 Standard_Boolean rational = &Weights != NULL;
214 Standard_Integer dim;
218 TColStd_Array1OfReal poles(1,dim*Poles.Length());
219 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
221 if (rational) PLib::SetPoles(Poles,Weights,poles);
222 else PLib::SetPoles(Poles,poles);
224 IncreaseDegree(Degree,NewDegree,Periodic,dim,poles,Knots,Mults,
225 newpoles,NewKnots,NewMults);
227 if (rational) PLib::GetPoles(newpoles,NewPoles,NewWeights);
228 else PLib::GetPoles(newpoles,NewPoles);
231 //=======================================================================
232 //function : Unperiodize
234 //=======================================================================
236 void BSplCLib::Unperiodize
237 (const Standard_Integer Degree,
238 const TColStd_Array1OfInteger& Mults,
239 const TColStd_Array1OfReal& Knots,
240 const Array1OfPoints& Poles,
241 const TColStd_Array1OfReal& Weights,
242 TColStd_Array1OfInteger& NewMults,
243 TColStd_Array1OfReal& NewKnots,
244 Array1OfPoints& NewPoles,
245 TColStd_Array1OfReal& NewWeights)
247 Standard_Boolean rational = &Weights != NULL;
248 Standard_Integer dim;
252 TColStd_Array1OfReal poles(1,dim*Poles.Length());
253 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
255 if (rational) PLib::SetPoles(Poles,Weights,poles);
256 else PLib::SetPoles(Poles,poles);
258 Unperiodize(Degree, dim, Mults, Knots, poles,
259 NewMults,NewKnots, newpoles);
261 if (rational) PLib::GetPoles(newpoles,NewPoles,NewWeights);
262 else PLib::GetPoles(newpoles,NewPoles);
265 //=======================================================================
266 //function : Trimming
268 //=======================================================================
270 void BSplCLib::Trimming(const Standard_Integer Degree,
271 const Standard_Boolean Periodic,
272 const TColStd_Array1OfReal& Knots,
273 const TColStd_Array1OfInteger& Mults,
274 const Array1OfPoints& Poles,
275 const TColStd_Array1OfReal& Weights,
276 const Standard_Real U1,
277 const Standard_Real U2,
278 TColStd_Array1OfReal& NewKnots,
279 TColStd_Array1OfInteger& NewMults,
280 Array1OfPoints& NewPoles,
281 TColStd_Array1OfReal& NewWeights)
283 Standard_Boolean rational = &Weights != NULL;
284 Standard_Integer dim;
288 TColStd_Array1OfReal poles(1,dim*Poles.Length());
289 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
291 if (rational) PLib::SetPoles(Poles,Weights,poles);
292 else PLib::SetPoles(Poles,poles);
294 Trimming(Degree, Periodic, dim, Knots, Mults, poles, U1, U2,
295 NewKnots, NewMults, newpoles);
297 if (rational) PLib::GetPoles(newpoles,NewPoles,NewWeights);
298 else PLib::GetPoles(newpoles,NewPoles);
301 //--------------------------------------------------------------------------
302 //ELEMENTARY COMPUTATIONS
303 //--------------------------------------------------------------------------
305 // All the following methods are methods of low level used in BSplCLib
306 // but also in BSplSLib (but not in Geom)
307 // At the creation time of this package there is no possibility
308 // to declare private methods of package and to declare friend
309 // methods of package. It could interesting to declare that BSplSLib
310 // is a package friend to BSplCLib because it uses all the basis methods
312 //--------------------------------------------------------------------------
314 //=======================================================================
315 //function : BuildEval
316 //purpose : builds the local array for evaluation
317 //=======================================================================
319 void BSplCLib::BuildEval(const Standard_Integer Degree,
320 const Standard_Integer Index,
321 const Array1OfPoints& Poles,
322 const TColStd_Array1OfReal& Weights,
325 Standard_Real w, *pole = &LP;
326 Standard_Integer PLower = Poles.Lower();
327 Standard_Integer PUpper = Poles.Upper();
329 Standard_Integer ip = PLower + Index - 1;
330 if (&Weights == NULL) {
331 for (i = 0; i <= Degree; i++) {
333 if (ip > PUpper) ip = PLower;
334 const Point& P = Poles(ip);
335 PointToCoords (pole,P,+0);
336 pole += Dimension_gen;
340 for (i = 0; i <= Degree; i++) {
342 if (ip > PUpper) ip = PLower;
343 const Point& P = Poles(ip);
344 pole[Dimension_gen] = w = Weights(ip);
345 PointToCoords (pole, P, * w);
346 pole += Dimension_gen + 1;
351 //=======================================================================
352 //function : PrepareEval
353 //purpose : stores data for Eval in the local arrays
354 // dc.poles and dc.knots
355 //=======================================================================
357 static void PrepareEval
359 Standard_Integer& index,
360 Standard_Integer& dim,
361 Standard_Boolean& rational,
362 const Standard_Integer Degree,
363 const Standard_Boolean Periodic,
364 const Array1OfPoints& Poles,
365 const TColStd_Array1OfReal& Weights,
366 const TColStd_Array1OfReal& Knots,
367 const TColStd_Array1OfInteger& Mults,
368 BSplCLib_DataContainer& dc)
371 BSplCLib::LocateParameter(Degree,Knots,Mults,u,Periodic,index,u);
374 BSplCLib::BuildKnots(Degree,index,Periodic,Knots,Mults,*dc.knots);
376 index -= Knots.Lower() + Degree;
378 index = BSplCLib::PoleIndex(Degree,index,Periodic,Mults);
380 // check truly rational
381 rational = (&Weights != NULL);
383 Standard_Integer WLower = Weights.Lower() + index;
384 rational = BSplCLib::IsRational(Weights, WLower, WLower + Degree);
389 dim = Dimension_gen + 1;
390 BSplCLib::BuildEval(Degree, index, Poles, Weights , *dc.poles);
394 BSplCLib::BuildEval(Degree, index, Poles, BSplCLib::NoWeights(), *dc.poles);
398 //=======================================================================
401 //=======================================================================
404 (const Standard_Real U,
405 const Standard_Integer Index,
406 const Standard_Integer Degree,
407 const Standard_Boolean Periodic,
408 const Array1OfPoints& Poles,
409 const TColStd_Array1OfReal& Weights,
410 const TColStd_Array1OfReal& Knots,
411 const TColStd_Array1OfInteger& Mults,
414 // Standard_Integer k,dim,index = Index;
415 Standard_Integer dim,index = Index;
417 Standard_Boolean rational;
418 BSplCLib_DataContainer dc(Degree);
419 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
420 BSplCLib::Eval(u,Degree,*dc.knots,dim,*dc.poles);
423 Standard_Real w = dc.poles[Dimension_gen];
424 CoordsToPoint (P, dc.poles, / w);
427 CoordsToPoint (P, dc.poles, );
430 //=======================================================================
433 //=======================================================================
436 (const Standard_Real U,
437 const Standard_Integer Index,
438 const Standard_Integer Degree,
439 const Standard_Boolean Periodic,
440 const Array1OfPoints& Poles,
441 const TColStd_Array1OfReal& Weights,
442 const TColStd_Array1OfReal& Knots,
443 const TColStd_Array1OfInteger& Mults,
447 Standard_Integer dim,index = Index;
449 Standard_Boolean rational;
450 BSplCLib_DataContainer dc(Degree);
451 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
452 BSplCLib::Bohm(u,Degree,1,*dc.knots,dim,*dc.poles);
453 Standard_Real *result = dc.poles;
455 PLib::RationalDerivative(Degree,1,Dimension_gen,*dc.poles,*dc.ders);
459 CoordsToPoint (P, result, );
460 CoordsToPoint (V, result + Dimension_gen, );
463 //=======================================================================
466 //=======================================================================
469 (const Standard_Real U,
470 const Standard_Integer Index,
471 const Standard_Integer Degree,
472 const Standard_Boolean Periodic,
473 const Array1OfPoints& Poles,
474 const TColStd_Array1OfReal& Weights,
475 const TColStd_Array1OfReal& Knots,
476 const TColStd_Array1OfInteger& Mults,
481 Standard_Integer dim,index = Index;
483 Standard_Boolean rational;
484 BSplCLib_DataContainer dc(Degree);
485 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
486 BSplCLib::Bohm(u,Degree,2,*dc.knots,dim,*dc.poles);
487 Standard_Real *result = dc.poles;
489 PLib::RationalDerivative(Degree,2,Dimension_gen,*dc.poles,*dc.ders);
493 CoordsToPoint (P, result, );
494 CoordsToPoint (V1, result + Dimension_gen, );
495 if (!rational && (Degree < 2))
498 CoordsToPoint (V2, result + 2 * Dimension_gen, );
501 //=======================================================================
504 //=======================================================================
507 (const Standard_Real U,
508 const Standard_Integer Index,
509 const Standard_Integer Degree,
510 const Standard_Boolean Periodic,
511 const Array1OfPoints& Poles,
512 const TColStd_Array1OfReal& Weights,
513 const TColStd_Array1OfReal& Knots,
514 const TColStd_Array1OfInteger& Mults,
520 Standard_Integer dim,index = Index;
522 Standard_Boolean rational;
523 BSplCLib_DataContainer dc(Degree);
524 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
525 BSplCLib::Bohm(u,Degree,3,*dc.knots,dim,*dc.poles);
526 Standard_Real *result = dc.poles;
528 PLib::RationalDerivative(Degree,3,Dimension_gen,*dc.poles,*dc.ders);
532 CoordsToPoint (P, result, );
533 CoordsToPoint (V1, result + Dimension_gen, );
534 if (!rational && (Degree < 2))
537 CoordsToPoint (V2, result + 2 * Dimension_gen, );
538 if (!rational && (Degree < 3))
541 CoordsToPoint (V3, result + 3 * Dimension_gen, );
544 //=======================================================================
547 //=======================================================================
550 (const Standard_Real U,
551 const Standard_Integer N,
552 const Standard_Integer Index,
553 const Standard_Integer Degree,
554 const Standard_Boolean Periodic,
555 const Array1OfPoints& Poles,
556 const TColStd_Array1OfReal& Weights,
557 const TColStd_Array1OfReal& Knots,
558 const TColStd_Array1OfInteger& Mults,
561 Standard_Integer dim,index = Index;
563 Standard_Boolean rational;
564 BSplCLib_DataContainer dc(Degree);
565 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
566 BSplCLib::Bohm(u,Degree,N,*dc.knots,dim,*dc.poles);
569 Standard_Real v[Dimension_gen];
570 PLib::RationalDerivative(Degree,N,Dimension_gen,*dc.poles,v[0],Standard_False);
571 CoordsToPoint (VN, v, );
577 Standard_Real *DN = dc.poles + N * Dimension_gen;
578 CoordsToPoint (VN, DN, );
583 //=======================================================================
584 //function : Solves a LU factored Matrix
586 //=======================================================================
589 BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
590 const Standard_Integer UpperBandWidth,
591 const Standard_Integer LowerBandWidth,
592 Array1OfPoints& PolesArray)
594 Standard_Real *PArray ;
595 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
597 return BSplCLib::SolveBandedSystem(Matrix,
604 //=======================================================================
605 //function : Solves a LU factored Matrix
606 //purpose : if HomogeneousFlag is 1 then the input and the output
607 // will be homogeneous that is no division or multiplication
608 // by weigths will happen. On the contrary if HomogeneousFlag
609 // is 0 then the poles will be multiplied first by the weights
610 // and after interpolation they will be devided by the weights
611 //=======================================================================
614 BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
615 const Standard_Integer UpperBandWidth,
616 const Standard_Integer LowerBandWidth,
617 const Standard_Boolean HomogeneousFlag,
618 Array1OfPoints& PolesArray,
619 TColStd_Array1OfReal& WeightsArray)
621 Standard_Real *PArray,
623 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
624 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
625 return BSplCLib::SolveBandedSystem(Matrix,
634 //=======================================================================
635 //function : Evaluates a Bspline function : uses the ExtrapMode
636 //purpose : the function is extrapolated using the Taylor expansion
637 // of degree ExtrapMode[0] to the left and the Taylor
638 // expansion of degree ExtrapMode[1] to the right
639 // if the HomogeneousFlag == True than the Poles are supposed
640 // to be stored homogeneously and the result will also be homogeneous
641 // Valid only if Weights
642 //=======================================================================
643 void BSplCLib::Eval(const Standard_Real Parameter,
644 const Standard_Boolean PeriodicFlag,
645 const Standard_Boolean HomogeneousFlag,
646 Standard_Integer& ExtrapMode,
647 const Standard_Integer Degree,
648 const TColStd_Array1OfReal& FlatKnots,
649 const Array1OfPoints& PolesArray,
650 const TColStd_Array1OfReal& WeightsArray,
652 Standard_Real& aWeight)
654 Standard_Real Inverse,
658 Standard_Integer kk ;
659 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
660 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
661 if (HomogeneousFlag) {
662 BSplCLib::Eval(Parameter,
671 BSplCLib::Eval(Parameter,
682 BSplCLib::Eval(Parameter,
693 Inverse = 1.0e0 / aWeight ;
695 for (kk = 0 ; kk < Dimension_gen ; kk++) {
700 for (kk = 0 ; kk < Dimension_gen ; kk++)
701 aPoint.SetCoord(kk + 1, P[kk]) ;
704 //=======================================================================
706 //purpose : Evaluates the polynomial cache of the Bspline Curve
708 //=======================================================================
709 void BSplCLib::CacheD0(const Standard_Real Parameter,
710 const Standard_Integer Degree,
711 const Standard_Real CacheParameter,
712 const Standard_Real SpanLenght,
713 const Array1OfPoints& PolesArray,
714 const TColStd_Array1OfReal& WeightsArray,
718 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
720 // the SpanLenght is the normalizing factor so that the polynomial is between
722 Standard_Real NewParameter, Inverse;
723 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
724 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
725 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
726 PLib::NoDerivativeEvalPolynomial(NewParameter,
729 Degree * Dimension_gen,
732 if (&WeightsArray != NULL) {
734 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
735 PLib::NoDerivativeEvalPolynomial(NewParameter,
742 Inverse = 1.0e0 / Inverse;
743 ModifyCoords (myPoint, *= Inverse);
747 //=======================================================================
749 //purpose : Evaluates the polynomial cache of the Bspline Curve
751 //=======================================================================
752 void BSplCLib::CacheD1(const Standard_Real Parameter,
753 const Standard_Integer Degree,
754 const Standard_Real CacheParameter,
755 const Standard_Real SpanLenght,
756 const Array1OfPoints& PolesArray,
757 const TColStd_Array1OfReal& WeightsArray,
762 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
764 // the SpanLenght is the normalizing factor so that the polynomial is between
766 Standard_Real LocalPDerivatives[Dimension_gen << 1] ;
767 // Standard_Real LocalWDerivatives[2], NewParameter, Inverse ;
768 Standard_Real LocalWDerivatives[2], NewParameter ;
771 PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
773 myPoint = (Standard_Real *) &aPoint ;
775 myVector = (Standard_Real *) &aVector ;
776 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
777 PLib::EvalPolynomial(NewParameter,
782 LocalPDerivatives[0]) ;
784 // unormalize derivatives since those are computed normalized
787 ModifyCoords (LocalPDerivatives + Dimension_gen, /= SpanLenght);
789 if (&WeightsArray != NULL) {
791 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
792 PLib::EvalPolynomial(NewParameter,
797 LocalWDerivatives[0]) ;
799 // unormalize the result since the polynomial stored in the cache
800 // is normalized between 0 and 1
802 LocalWDerivatives[1] /= SpanLenght ;
804 PLib::RationalDerivatives(1,
806 LocalPDerivatives[0],
807 LocalWDerivatives[0],
808 LocalPDerivatives[0]) ;
811 CopyCoords (myPoint, LocalPDerivatives);
812 CopyCoords (myVector, LocalPDerivatives + Dimension_gen);
815 //=======================================================================
817 //purpose : Evaluates the polynomial cache of the Bspline Curve
819 //=======================================================================
820 void BSplCLib::CacheD2(const Standard_Real Parameter,
821 const Standard_Integer Degree,
822 const Standard_Real CacheParameter,
823 const Standard_Real SpanLenght,
824 const Array1OfPoints& PolesArray,
825 const TColStd_Array1OfReal& WeightsArray,
831 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
833 // the SpanLenght is the normalizing factor so that the polynomial is between
835 Standard_Integer ii,Index,EndIndex;
836 Standard_Real LocalPDerivatives[(Dimension_gen << 1) + Dimension_gen] ;
837 // Standard_Real LocalWDerivatives[3], NewParameter, Factor, Inverse ;
838 Standard_Real LocalWDerivatives[3], NewParameter, Factor ;
839 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
840 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
841 Standard_Real * myVector1 = (Standard_Real *) &aVector1 ;
842 Standard_Real * myVector2 = (Standard_Real *) &aVector2 ;
843 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
844 PLib::EvalPolynomial(NewParameter,
849 LocalPDerivatives[0]) ;
851 // unormalize derivatives since those are computed normalized
853 Factor = 1.0e0/ SpanLenght ;
854 Index = Dimension_gen ;
855 EndIndex = Min (2, Degree) ;
857 for (ii = 1 ; ii <= EndIndex ; ii++) {
858 ModifyCoords (LocalPDerivatives + Index, *= Factor);
859 Factor /= SpanLenght ;
860 Index += Dimension_gen;
863 Index = (Degree + 1) * Dimension_gen;
864 for (ii = Degree ; ii < 2 ; ii++) {
865 NullifyCoords (LocalPDerivatives + Index);
866 Index += Dimension_gen;
869 if (&WeightsArray != NULL) {
871 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
873 PLib::EvalPolynomial(NewParameter,
878 LocalWDerivatives[0]) ;
880 for (ii = Degree + 1 ; ii <= 2 ; ii++) {
881 LocalWDerivatives[ii] = 0.0e0 ;
884 // unormalize the result since the polynomial stored in the cache
885 // is normalized between 0 and 1
887 Factor = 1.0e0 / SpanLenght ;
889 for (ii = 1 ; ii <= EndIndex ; ii++) {
890 LocalWDerivatives[ii] *= Factor ;
891 Factor /= SpanLenght ;
893 PLib::RationalDerivatives(2,
895 LocalPDerivatives[0],
896 LocalWDerivatives[0],
897 LocalPDerivatives[0]) ;
900 CopyCoords (myPoint, LocalPDerivatives);
901 CopyCoords (myVector1, LocalPDerivatives + Dimension_gen);
902 CopyCoords (myVector2, LocalPDerivatives + Dimension_gen * 2);
905 //=======================================================================
907 //purpose : Evaluates the polynomial cache of the Bspline Curve
909 //=======================================================================
910 void BSplCLib::CacheD3(const Standard_Real Parameter,
911 const Standard_Integer Degree,
912 const Standard_Real CacheParameter,
913 const Standard_Real SpanLenght,
914 const Array1OfPoints& PolesArray,
915 const TColStd_Array1OfReal& WeightsArray,
922 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
924 // the SpanLenght is the normalizing factor so that the polynomial is between
926 Standard_Integer ii, Index, EndIndex;
927 Standard_Real LocalPDerivatives[Dimension_gen << 2] ;
928 // Standard_Real LocalWDerivatives[4], Factor, NewParameter, Inverse ;
929 Standard_Real LocalWDerivatives[4], Factor, NewParameter ;
930 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
931 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
932 Standard_Real * myVector1 = (Standard_Real *) &aVector1 ;
933 Standard_Real * myVector2 = (Standard_Real *) &aVector2 ;
934 Standard_Real * myVector3 = (Standard_Real *) &aVector3 ;
935 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
936 PLib::EvalPolynomial(NewParameter,
941 LocalPDerivatives[0]) ;
943 Index = (Degree + 1) * Dimension_gen;
944 for (ii = Degree ; ii < 3 ; ii++) {
945 NullifyCoords (LocalPDerivatives + Index);
946 Index += Dimension_gen;
950 // unormalize derivatives since those are computed normalized
952 Factor = 1.0e0 / SpanLenght ;
953 Index = Dimension_gen ;
954 EndIndex = Min(3,Degree) ;
956 for (ii = 1 ; ii <= EndIndex ; ii++) {
957 ModifyCoords (LocalPDerivatives + Index, *= Factor);
958 Factor /= SpanLenght;
959 Index += Dimension_gen;
962 if (&WeightsArray != NULL) {
964 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
966 PLib::EvalPolynomial(NewParameter,
971 LocalWDerivatives[0]) ;
973 // unormalize the result since the polynomial stored in the cache
974 // is normalized between 0 and 1
976 Factor = 1.0e0 / SpanLenght ;
978 for (ii = 1 ; ii <= EndIndex ; ii++) {
979 LocalWDerivatives[ii] *= Factor ;
980 Factor /= SpanLenght ;
983 for (ii = (Degree + 1) ; ii <= 3 ; ii++) {
984 LocalWDerivatives[ii] = 0.0e0 ;
986 PLib::RationalDerivatives(3,
988 LocalPDerivatives[0],
989 LocalWDerivatives[0],
990 LocalPDerivatives[0]) ;
993 CopyCoords (myPoint, LocalPDerivatives);
994 CopyCoords (myVector1, LocalPDerivatives + Dimension_gen);
995 CopyCoords (myVector2, LocalPDerivatives + Dimension_gen * 2);
996 CopyCoords (myVector3, LocalPDerivatives + Dimension_gen * 3);
999 //=======================================================================
1000 //function : BuildCache
1001 //purpose : Stores theTaylor expansion normalized between 0,1 in the
1002 // Cache : in case of a rational function the Poles are
1003 // stored in homogeneous form
1004 //=======================================================================
1006 void BSplCLib::BuildCache
1007 (const Standard_Real U,
1008 const Standard_Real SpanDomain,
1009 const Standard_Boolean Periodic,
1010 const Standard_Integer Degree,
1011 const TColStd_Array1OfReal& FlatKnots,
1012 const Array1OfPoints& Poles,
1013 const TColStd_Array1OfReal& Weights,
1014 Array1OfPoints& CachePoles,
1015 TColStd_Array1OfReal& CacheWeights)
1017 Standard_Integer ii,
1021 Standard_Real u = U,
1023 Standard_Boolean rational;
1025 BSplCLib_DataContainer dc(Degree);
1035 (BSplCLib::NoMults()),
1038 // Watch out : PrepareEval checks if locally the Bspline is polynomial
1039 // therefore rational flag could be set to False even if there are
1040 // Weights. The Dimension is set accordingly.
1043 BSplCLib::Bohm(u,Degree,Degree,*dc.knots,Dimension,*dc.poles);
1045 LocalValue = 1.0e0 ;
1050 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1051 CoordsToPoint (CachePoles(ii), dc.poles + LocalIndex, * LocalValue);
1052 LocalIndex += Dimension_gen + 1;
1053 LocalValue *= SpanDomain / (Standard_Real) ii ;
1056 LocalIndex = Dimension_gen;
1057 LocalValue = 1.0e0 ;
1058 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1059 CacheWeights(ii) = dc.poles[LocalIndex] * LocalValue ;
1060 LocalIndex += Dimension_gen + 1;
1061 LocalValue *= SpanDomain / (Standard_Real) ii ;
1066 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1067 CoordsToPoint (CachePoles(ii), dc.poles + LocalIndex, * LocalValue);
1068 LocalIndex += Dimension_gen;
1069 LocalValue *= SpanDomain / (Standard_Real) ii ;
1072 if (&Weights != NULL) {
1073 for (ii = 1 ; ii <= Degree + 1 ; ii++)
1074 CacheWeights(ii) = 0.0e0 ;
1075 CacheWeights(1) = 1.0e0 ;
1080 //=======================================================================
1081 //function : Interpolate
1083 //=======================================================================
1085 void BSplCLib::Interpolate(const Standard_Integer Degree,
1086 const TColStd_Array1OfReal& FlatKnots,
1087 const TColStd_Array1OfReal& Parameters,
1088 const TColStd_Array1OfInteger& ContactOrderArray,
1089 Array1OfPoints& Poles,
1090 Standard_Integer& InversionProblem)
1093 Standard_Real *PArray ;
1095 PArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1097 BSplCLib::Interpolate(Degree,
1106 //=======================================================================
1107 //function : Interpolate
1109 //=======================================================================
1111 void BSplCLib::Interpolate(const Standard_Integer Degree,
1112 const TColStd_Array1OfReal& FlatKnots,
1113 const TColStd_Array1OfReal& Parameters,
1114 const TColStd_Array1OfInteger& ContactOrderArray,
1115 Array1OfPoints& Poles,
1116 TColStd_Array1OfReal& Weights,
1117 Standard_Integer& InversionProblem)
1119 Standard_Real *PArray,
1121 PArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1122 WArray = (Standard_Real *) &Weights(Weights.Lower()) ;
1123 BSplCLib::Interpolate(Degree,
1133 //=======================================================================
1134 //function : MovePoint
1135 //purpose : Find the new poles which allows an old point (with a
1136 // given u as parameter) to reach a new position
1137 //=======================================================================
1139 void BSplCLib::MovePoint (const Standard_Real U,
1140 const Vector& Displ,
1141 const Standard_Integer Index1,
1142 const Standard_Integer Index2,
1143 const Standard_Integer Degree,
1144 const Standard_Boolean Rational,
1145 const Array1OfPoints& Poles,
1146 const TColStd_Array1OfReal& Weights,
1147 const TColStd_Array1OfReal& FlatKnots,
1148 Standard_Integer& FirstIndex,
1149 Standard_Integer& LastIndex,
1150 Array1OfPoints& NewPoles)
1152 // calculate the BSplineBasis in the parameter U
1153 Standard_Integer FirstNonZeroBsplineIndex;
1154 math_Matrix BSplineBasis(1, 1,
1156 Standard_Integer ErrorCode =
1157 BSplCLib::EvalBsplineBasis(1,
1162 FirstNonZeroBsplineIndex,
1164 if (ErrorCode != 0) {
1168 for (Standard_Integer i=Poles.Lower(); i<=Poles.Upper(); i++) {
1169 NewPoles(i) = Poles(i);
1174 // find the span which is predominant for parameter U
1175 FirstIndex = FirstNonZeroBsplineIndex;
1176 LastIndex = FirstNonZeroBsplineIndex + Degree ;
1177 if (FirstIndex < Index1) FirstIndex = Index1;
1178 if (LastIndex > Index2) LastIndex = Index2;
1180 Standard_Real maxValue = 0.0;
1181 Standard_Integer i, kk1=0, kk2, ii;
1183 for (i = FirstIndex-FirstNonZeroBsplineIndex+1;
1184 i <= LastIndex-FirstNonZeroBsplineIndex+1; i++) {
1185 if (BSplineBasis(1,i) > maxValue) {
1186 kk1 = i + FirstNonZeroBsplineIndex - 1;
1187 maxValue = BSplineBasis(1,i);
1191 // find a kk2 if symetriy
1193 i = kk1 - FirstNonZeroBsplineIndex + 2;
1194 if ((kk1+1) <= LastIndex) {
1195 if (Abs(BSplineBasis(1, kk1-FirstNonZeroBsplineIndex+2) - maxValue) < 1.e-10) {
1200 // compute the vector of displacement
1201 Standard_Real D1 = 0.0;
1202 Standard_Real D2 = 0.0;
1203 Standard_Real hN, Coef, Dval;
1205 for (i = 1; i <= Degree+1; i++) {
1206 ii = i + FirstNonZeroBsplineIndex - 1;
1208 hN = Weights(ii)*BSplineBasis(1, i);
1212 hN = BSplineBasis(1, i);
1214 if (ii >= FirstIndex && ii <= LastIndex) {
1218 else if (ii > kk2) {
1224 D1 += 1./(Dval + 1.) * hN;
1235 // compute the new poles
1237 for (i=Poles.Lower(); i<=Poles.Upper(); i++) {
1238 if (i >= FirstIndex && i <= LastIndex) {
1248 NewPoles(i) = Poles(i).Translated((Coef/(Dval+1.))*Displ);
1251 NewPoles(i) = Poles(i);
1256 //=======================================================================
1257 //function : MovePoint
1258 //purpose : Find the new poles which allows an old point (with a
1259 // given u as parameter) to reach a new position
1260 //=======================================================================
1262 //=======================================================================
1263 //function : MovePointAndTangent
1265 //=======================================================================
1267 void BSplCLib::MovePointAndTangent (const Standard_Real U,
1268 const Vector& Delta,
1269 const Vector& DeltaDerivatives,
1270 const Standard_Real Tolerance,
1271 const Standard_Integer Degree,
1272 const Standard_Boolean Rational,
1273 const Standard_Integer StartingCondition,
1274 const Standard_Integer EndingCondition,
1275 const Array1OfPoints& Poles,
1276 const TColStd_Array1OfReal& Weights,
1277 const TColStd_Array1OfReal& FlatKnots,
1278 Array1OfPoints& NewPoles,
1279 Standard_Integer & ErrorStatus)
1281 Standard_Real *delta_array,
1282 *delta_derivative_array,
1286 Standard_Integer num_poles ;
1287 num_poles = Poles.Length() ;
1289 if (NewPoles.Length() != num_poles) {
1290 Standard_ConstructionError::Raise();
1292 delta_array = (Standard_Real *) &Delta ;
1293 delta_derivative_array = (Standard_Real *)&DeltaDerivatives ;
1294 poles_array = (Standard_Real *) &Poles(Poles.Lower()) ;
1296 new_poles_array = (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1297 MovePointAndTangent(U,
1300 delta_derivative_array[0],
1313 //=======================================================================
1314 //function : Resolution
1316 //=======================================================================
1318 void BSplCLib::Resolution(const Array1OfPoints& Poles,
1319 const TColStd_Array1OfReal& Weights,
1320 const Standard_Integer NumPoles,
1321 const TColStd_Array1OfReal& FlatKnots,
1322 const Standard_Integer Degree,
1323 const Standard_Real Tolerance3D,
1324 Standard_Real& UTolerance)
1326 Standard_Real *PolesArray ;
1327 PolesArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1328 BSplCLib::Resolution(PolesArray[0],
1338 //=======================================================================
1339 //function : FunctionMultiply
1341 //=======================================================================
1343 void BSplCLib::FunctionMultiply
1344 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1345 const Standard_Integer BSplineDegree,
1346 const TColStd_Array1OfReal & BSplineFlatKnots,
1347 const Array1OfPoints & Poles,
1348 const TColStd_Array1OfReal & FlatKnots,
1349 const Standard_Integer NewDegree,
1350 Array1OfPoints & NewPoles,
1351 Standard_Integer & Status)
1353 Standard_Integer num_bspline_poles =
1354 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1355 Standard_Integer num_new_poles =
1356 FlatKnots.Length() - NewDegree - 1 ;
1358 if (Poles.Length() != num_bspline_poles ||
1359 NewPoles.Length() != num_new_poles) {
1360 Standard_ConstructionError::Raise();
1362 Standard_Real * array_of_poles =
1363 (Standard_Real *) &Poles(Poles.Lower()) ;
1364 Standard_Real * array_of_new_poles =
1365 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1366 BSplCLib::FunctionMultiply(FunctionPtr,
1373 array_of_new_poles[0],
1377 //=======================================================================
1378 //function : FunctionReparameterise
1380 //=======================================================================
1382 void BSplCLib::FunctionReparameterise
1383 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1384 const Standard_Integer BSplineDegree,
1385 const TColStd_Array1OfReal & BSplineFlatKnots,
1386 const Array1OfPoints & Poles,
1387 const TColStd_Array1OfReal & FlatKnots,
1388 const Standard_Integer NewDegree,
1389 Array1OfPoints & NewPoles,
1390 Standard_Integer & Status)
1392 Standard_Integer num_bspline_poles =
1393 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1394 Standard_Integer num_new_poles =
1395 FlatKnots.Length() - NewDegree - 1 ;
1397 if (Poles.Length() != num_bspline_poles ||
1398 NewPoles.Length() != num_new_poles) {
1399 Standard_ConstructionError::Raise();
1401 Standard_Real * array_of_poles =
1402 (Standard_Real *) &Poles(Poles.Lower()) ;
1403 Standard_Real * array_of_new_poles =
1404 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1405 BSplCLib::FunctionReparameterise(FunctionPtr,
1412 array_of_new_poles[0],