Warning, /include/opencascade/BSplCLib_CurveComputation.gxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014
0015 // xab : modified 15-Mar-94 added EvalBSplineMatrix, FactorBandedMatrix, SolveBandedSystem
0016 // Eval, BuildCache, cacheD0, cacheD1, cacheD2, cacheD3, LocalMatrix,
0017 // EvalPolynomial, RationalDerivatives.
0018 // xab : 22-Mar-94 : fixed rational problem in BuildCache
0019 // xab : 12-Mar-96 : added MovePointAndTangent
0020 #include <TColStd_Array1OfInteger.hxx>
0021 #include <TColStd_Array1OfReal.hxx>
0022 #include <TColStd_Array2OfReal.hxx>
0023 #include <gp_Vec2d.hxx>
0024 #include <Standard_ConstructionError.hxx>
0025 #include <PLib.hxx>
0026 #include <math_Matrix.hxx>
0027
0028 //=======================================================================
0029 //struct : BSplCLib_DataContainer
0030 //purpose: Auxiliary structure providing buffers for poles and knots used in
0031 // evaluation of bspline (allocated in the stack)
0032 //=======================================================================
0033
0034 struct BSplCLib_DataContainer
0035 {
0036 BSplCLib_DataContainer(Standard_Integer Degree)
0037 {
0038 (void)Degree; // avoid compiler warning
0039 Standard_OutOfRange_Raise_if (Degree > BSplCLib::MaxDegree() ||
0040 BSplCLib::MaxDegree() > 25,
0041 "BSplCLib: bspline degree is greater than maximum supported");
0042 }
0043
0044 Standard_Real poles[(25+1)*(Dimension_gen+1)];
0045 Standard_Real knots[2*25];
0046 Standard_Real ders[Dimension_gen*4];
0047 };
0048
0049 //=======================================================================
0050 //function : Reverse
0051 //purpose :
0052 //=======================================================================
0053
0054 void BSplCLib::Reverse(Array1OfPoints& Poles,
0055 const Standard_Integer L)
0056 {
0057 Standard_Integer i, l = L;
0058 l = Poles.Lower() + (l-Poles.Lower()) % (Poles.Upper()-Poles.Lower()+1);
0059
0060 Array1OfPoints temp(0,Poles.Length()-1);
0061
0062 for (i = Poles.Lower(); i <= l; i++)
0063 temp(l-i) = Poles(i);
0064
0065 for (i = l+1; i <= Poles.Upper(); i++)
0066 temp(l-Poles.Lower()+Poles.Upper()-i+1) = Poles(i);
0067
0068 for (i = Poles.Lower(); i <= Poles.Upper(); i++)
0069 Poles(i) = temp(i-Poles.Lower());
0070 }
0071
0072 //
0073 // CURVES MODIFICATIONS
0074 //
0075
0076 //=======================================================================
0077 //function : RemoveKnot
0078 //purpose :
0079 //=======================================================================
0080
0081 Standard_Boolean BSplCLib::RemoveKnot
0082 (const Standard_Integer Index,
0083 const Standard_Integer Mult,
0084 const Standard_Integer Degree,
0085 const Standard_Boolean Periodic,
0086 const Array1OfPoints& Poles,
0087 const TColStd_Array1OfReal* Weights,
0088 const TColStd_Array1OfReal& Knots,
0089 const TColStd_Array1OfInteger& Mults,
0090 Array1OfPoints& NewPoles,
0091 TColStd_Array1OfReal* NewWeights,
0092 TColStd_Array1OfReal& NewKnots,
0093 TColStd_Array1OfInteger& NewMults,
0094 const Standard_Real Tolerance)
0095 {
0096 Standard_Boolean rational = Weights != NULL;
0097 Standard_Integer dim;
0098 dim = Dimension_gen;
0099 if (rational) dim++;
0100
0101 TColStd_Array1OfReal poles(1,dim*Poles.Length());
0102 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
0103
0104 if (rational) PLib::SetPoles(Poles,*Weights,poles);
0105 else PLib::SetPoles(Poles,poles);
0106
0107 if (!RemoveKnot(Index,Mult,Degree,Periodic,dim,
0108 poles,Knots,Mults,newpoles,NewKnots,NewMults,Tolerance))
0109 return Standard_False;
0110
0111 if (rational) PLib::GetPoles(newpoles,NewPoles,*NewWeights);
0112 else PLib::GetPoles(newpoles,NewPoles);
0113 return Standard_True;
0114 }
0115
0116 //=======================================================================
0117 //function : InsertKnots
0118 //purpose : insert an array of knots and multiplicities
0119 //=======================================================================
0120
0121 void BSplCLib::InsertKnots
0122 (const Standard_Integer Degree,
0123 const Standard_Boolean Periodic,
0124 const Array1OfPoints& Poles,
0125 const TColStd_Array1OfReal* Weights,
0126 const TColStd_Array1OfReal& Knots,
0127 const TColStd_Array1OfInteger& Mults,
0128 const TColStd_Array1OfReal& AddKnots,
0129 const TColStd_Array1OfInteger* AddMults,
0130 Array1OfPoints& NewPoles,
0131 TColStd_Array1OfReal* NewWeights,
0132 TColStd_Array1OfReal& NewKnots,
0133 TColStd_Array1OfInteger& NewMults,
0134 const Standard_Real Epsilon,
0135 const Standard_Boolean Add)
0136 {
0137 Standard_Boolean rational = Weights != NULL;
0138 Standard_Integer dim;
0139 dim = Dimension_gen;
0140 if (rational) dim++;
0141
0142 TColStd_Array1OfReal poles(1,dim*Poles.Length());
0143 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
0144
0145 if (rational) PLib::SetPoles(Poles,*Weights,poles);
0146 else PLib::SetPoles(Poles,poles);
0147
0148 InsertKnots(Degree,Periodic,dim,poles,Knots,Mults,
0149 AddKnots,AddMults,newpoles,NewKnots,NewMults,Epsilon,Add);
0150
0151 if (rational) PLib::GetPoles(newpoles,NewPoles,*NewWeights);
0152 else PLib::GetPoles(newpoles,NewPoles);
0153 }
0154
0155 //=======================================================================
0156 //function : InsertKnot
0157 //purpose :
0158 //=======================================================================
0159
0160 void BSplCLib::InsertKnot(const Standard_Integer ,
0161 const Standard_Real U,
0162 const Standard_Integer UMult,
0163 const Standard_Integer Degree,
0164 const Standard_Boolean Periodic,
0165 const Array1OfPoints& Poles,
0166 const TColStd_Array1OfReal* Weights,
0167 const TColStd_Array1OfReal& Knots,
0168 const TColStd_Array1OfInteger& Mults,
0169 Array1OfPoints& NewPoles,
0170 TColStd_Array1OfReal* NewWeights)
0171 {
0172 TColStd_Array1OfReal k(1,1);
0173 k(1) = U;
0174 TColStd_Array1OfInteger m(1,1);
0175 m(1) = UMult;
0176 TColStd_Array1OfReal nk(1,Knots.Length()+1);
0177 TColStd_Array1OfInteger nm(1,Knots.Length()+1);
0178 InsertKnots(Degree,Periodic,Poles,Weights,Knots,Mults,
0179 k,&m,NewPoles,NewWeights,nk,nm,Epsilon(U));
0180 }
0181
0182 //=======================================================================
0183 //function : RaiseMultiplicity
0184 //purpose :
0185 //=======================================================================
0186
0187 void BSplCLib::RaiseMultiplicity(const Standard_Integer KnotIndex,
0188 const Standard_Integer Mult,
0189 const Standard_Integer Degree,
0190 const Standard_Boolean Periodic,
0191 const Array1OfPoints& Poles,
0192 const TColStd_Array1OfReal* Weights,
0193 const TColStd_Array1OfReal& Knots,
0194 const TColStd_Array1OfInteger& Mults,
0195 Array1OfPoints& NewPoles,
0196 TColStd_Array1OfReal* NewWeights)
0197 {
0198 TColStd_Array1OfReal k(1,1);
0199 k(1) = Knots(KnotIndex);
0200 TColStd_Array1OfInteger m(1,1);
0201 m(1) = Mult - Mults(KnotIndex);
0202 TColStd_Array1OfReal nk(1,Knots.Length());
0203 TColStd_Array1OfInteger nm(1,Knots.Length());
0204 InsertKnots(Degree,Periodic,Poles,Weights,Knots,Mults,
0205 k,&m,NewPoles,NewWeights,nk,nm,Epsilon(k(1)));
0206 }
0207
0208 //=======================================================================
0209 //function : IncreaseDegree
0210 //purpose :
0211 //=======================================================================
0212
0213 void BSplCLib::IncreaseDegree
0214 (const Standard_Integer Degree,
0215 const Standard_Integer NewDegree,
0216 const Standard_Boolean Periodic,
0217 const Array1OfPoints& Poles,
0218 const TColStd_Array1OfReal* Weights,
0219 const TColStd_Array1OfReal& Knots,
0220 const TColStd_Array1OfInteger& Mults,
0221 Array1OfPoints& NewPoles,
0222 TColStd_Array1OfReal* NewWeights,
0223 TColStd_Array1OfReal& NewKnots,
0224 TColStd_Array1OfInteger& NewMults)
0225 {
0226 Standard_Boolean rational = Weights != NULL;
0227 Standard_Integer dim;
0228 dim = Dimension_gen;
0229 if (rational) dim++;
0230
0231 TColStd_Array1OfReal poles(1,dim*Poles.Length());
0232 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
0233
0234 if (rational) PLib::SetPoles(Poles,*Weights,poles);
0235 else PLib::SetPoles(Poles,poles);
0236
0237 IncreaseDegree(Degree,NewDegree,Periodic,dim,poles,Knots,Mults,
0238 newpoles,NewKnots,NewMults);
0239
0240 if (rational) PLib::GetPoles(newpoles,NewPoles,*NewWeights);
0241 else PLib::GetPoles(newpoles,NewPoles);
0242 }
0243
0244 //=======================================================================
0245 //function : Unperiodize
0246 //purpose :
0247 //=======================================================================
0248
0249 void BSplCLib::Unperiodize
0250 (const Standard_Integer Degree,
0251 const TColStd_Array1OfInteger& Mults,
0252 const TColStd_Array1OfReal& Knots,
0253 const Array1OfPoints& Poles,
0254 const TColStd_Array1OfReal* Weights,
0255 TColStd_Array1OfInteger& NewMults,
0256 TColStd_Array1OfReal& NewKnots,
0257 Array1OfPoints& NewPoles,
0258 TColStd_Array1OfReal* NewWeights)
0259 {
0260 Standard_Boolean rational = Weights != NULL;
0261 Standard_Integer dim;
0262 dim = Dimension_gen;
0263 if (rational) dim++;
0264
0265 TColStd_Array1OfReal poles(1,dim*Poles.Length());
0266 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
0267
0268 if (rational) PLib::SetPoles(Poles,*Weights,poles);
0269 else PLib::SetPoles(Poles,poles);
0270
0271 Unperiodize(Degree, dim, Mults, Knots, poles,
0272 NewMults,NewKnots, newpoles);
0273
0274 if (rational) PLib::GetPoles(newpoles,NewPoles,*NewWeights);
0275 else PLib::GetPoles(newpoles,NewPoles);
0276 }
0277
0278 //=======================================================================
0279 //function : Trimming
0280 //purpose :
0281 //=======================================================================
0282
0283 void BSplCLib::Trimming(const Standard_Integer Degree,
0284 const Standard_Boolean Periodic,
0285 const TColStd_Array1OfReal& Knots,
0286 const TColStd_Array1OfInteger& Mults,
0287 const Array1OfPoints& Poles,
0288 const TColStd_Array1OfReal* Weights,
0289 const Standard_Real U1,
0290 const Standard_Real U2,
0291 TColStd_Array1OfReal& NewKnots,
0292 TColStd_Array1OfInteger& NewMults,
0293 Array1OfPoints& NewPoles,
0294 TColStd_Array1OfReal* NewWeights)
0295 {
0296 Standard_Boolean rational = Weights != NULL;
0297 Standard_Integer dim;
0298 dim = Dimension_gen;
0299 if (rational) dim++;
0300
0301 TColStd_Array1OfReal poles(1,dim*Poles.Length());
0302 TColStd_Array1OfReal newpoles(1,dim*NewPoles.Length());
0303
0304 if (rational) PLib::SetPoles(Poles,*Weights,poles);
0305 else PLib::SetPoles(Poles,poles);
0306
0307 Trimming(Degree, Periodic, dim, Knots, Mults, poles, U1, U2,
0308 NewKnots, NewMults, newpoles);
0309
0310 if (rational) PLib::GetPoles(newpoles,NewPoles,*NewWeights);
0311 else PLib::GetPoles(newpoles,NewPoles);
0312 }
0313
0314 //--------------------------------------------------------------------------
0315 //ELEMENTARY COMPUTATIONS
0316 //--------------------------------------------------------------------------
0317 //
0318 // All the following methods are methods of low level used in BSplCLib
0319 // but also in BSplSLib (but not in Geom)
0320 // At the creation time of this package there is no possibility
0321 // to declare private methods of package and to declare friend
0322 // methods of package. It could interesting to declare that BSplSLib
0323 // is a package friend to BSplCLib because it uses all the basis methods
0324 // of BSplCLib.
0325 //--------------------------------------------------------------------------
0326
0327 //=======================================================================
0328 //function : BuildEval
0329 //purpose : builds the local array for evaluation
0330 //=======================================================================
0331
0332 void BSplCLib::BuildEval(const Standard_Integer Degree,
0333 const Standard_Integer Index,
0334 const Array1OfPoints& Poles,
0335 const TColStd_Array1OfReal* Weights,
0336 Standard_Real& LP)
0337 {
0338 Standard_Real w, *pole = &LP;
0339 Standard_Integer PLower = Poles.Lower();
0340 Standard_Integer PUpper = Poles.Upper();
0341 Standard_Integer i;
0342 Standard_Integer ip = PLower + Index - 1;
0343 if (Weights == NULL) {
0344 for (i = 0; i <= Degree; i++) {
0345 ip++;
0346 if (ip > PUpper) ip = PLower;
0347 const Point& P = Poles(ip);
0348 PointToCoords (pole,P,+0);
0349 pole += Dimension_gen;
0350 }
0351 }
0352 else {
0353 for (i = 0; i <= Degree; i++) {
0354 ip++;
0355 if (ip > PUpper) ip = PLower;
0356 const Point& P = Poles(ip);
0357 pole[Dimension_gen] = w = (*Weights)(ip);
0358 PointToCoords (pole, P, * w);
0359 pole += Dimension_gen + 1;
0360 }
0361 }
0362 }
0363
0364 //=======================================================================
0365 //function : PrepareEval
0366 //purpose : stores data for Eval in the local arrays
0367 // dc.poles and dc.knots
0368 //=======================================================================
0369
0370 static void PrepareEval
0371 (Standard_Real& u,
0372 Standard_Integer& index,
0373 Standard_Integer& dim,
0374 Standard_Boolean& rational,
0375 const Standard_Integer Degree,
0376 const Standard_Boolean Periodic,
0377 const Array1OfPoints& Poles,
0378 const TColStd_Array1OfReal* Weights,
0379 const TColStd_Array1OfReal& Knots,
0380 const TColStd_Array1OfInteger* Mults,
0381 BSplCLib_DataContainer& dc)
0382 {
0383 // Set the Index
0384 BSplCLib::LocateParameter(Degree,Knots,Mults,u,Periodic,index,u);
0385
0386 // make the knots
0387 BSplCLib::BuildKnots(Degree,index,Periodic,Knots,Mults,*dc.knots);
0388 if (Mults == NULL)
0389 index -= Knots.Lower() + Degree;
0390 else
0391 index = BSplCLib::PoleIndex(Degree,index,Periodic,*Mults);
0392
0393 // check truly rational
0394 rational = (Weights != NULL);
0395 if (rational) {
0396 Standard_Integer WLower = Weights->Lower() + index;
0397 rational = BSplCLib::IsRational(*Weights, WLower, WLower + Degree);
0398 }
0399
0400 // make the poles
0401 if (rational) {
0402 dim = Dimension_gen + 1;
0403 BSplCLib::BuildEval(Degree, index, Poles, Weights , *dc.poles);
0404 }
0405 else {
0406 dim = Dimension_gen;
0407 BSplCLib::BuildEval(Degree, index, Poles, BSplCLib::NoWeights(), *dc.poles);
0408 }
0409 }
0410
0411 //=======================================================================
0412 //function : D0
0413 //purpose :
0414 //=======================================================================
0415
0416 void BSplCLib::D0
0417 (const Standard_Real U,
0418 const Standard_Integer Index,
0419 const Standard_Integer Degree,
0420 const Standard_Boolean Periodic,
0421 const Array1OfPoints& Poles,
0422 const TColStd_Array1OfReal* Weights,
0423 const TColStd_Array1OfReal& Knots,
0424 const TColStd_Array1OfInteger* Mults,
0425 Point& P)
0426 {
0427 // Standard_Integer k,dim,index = Index;
0428 Standard_Integer dim,index = Index;
0429 Standard_Real u = U;
0430 Standard_Boolean rational;
0431 BSplCLib_DataContainer dc(Degree);
0432 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
0433 BSplCLib::Eval(u,Degree,*dc.knots,dim,*dc.poles);
0434
0435 if (rational) {
0436 Standard_Real w = dc.poles[Dimension_gen];
0437 CoordsToPoint (P, dc.poles, / w);
0438 }
0439 else
0440 CoordsToPoint (P, dc.poles, );
0441 }
0442
0443 //=======================================================================
0444 //function : D1
0445 //purpose :
0446 //=======================================================================
0447
0448 void BSplCLib::D1
0449 (const Standard_Real U,
0450 const Standard_Integer Index,
0451 const Standard_Integer Degree,
0452 const Standard_Boolean Periodic,
0453 const Array1OfPoints& Poles,
0454 const TColStd_Array1OfReal* Weights,
0455 const TColStd_Array1OfReal& Knots,
0456 const TColStd_Array1OfInteger* Mults,
0457 Point& P,
0458 Vector& V)
0459 {
0460 Standard_Integer dim,index = Index;
0461 Standard_Real u = U;
0462 Standard_Boolean rational;
0463 BSplCLib_DataContainer dc(Degree);
0464 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
0465 BSplCLib::Bohm(u,Degree,1,*dc.knots,dim,*dc.poles);
0466 Standard_Real *result = dc.poles;
0467 if (rational) {
0468 PLib::RationalDerivative(Degree,1,Dimension_gen,*dc.poles,*dc.ders);
0469 result = dc.ders;
0470 }
0471
0472 CoordsToPoint (P, result, );
0473 CoordsToPoint (V, result + Dimension_gen, );
0474 }
0475
0476 //=======================================================================
0477 //function : D2
0478 //purpose :
0479 //=======================================================================
0480
0481 void BSplCLib::D2
0482 (const Standard_Real U,
0483 const Standard_Integer Index,
0484 const Standard_Integer Degree,
0485 const Standard_Boolean Periodic,
0486 const Array1OfPoints& Poles,
0487 const TColStd_Array1OfReal* Weights,
0488 const TColStd_Array1OfReal& Knots,
0489 const TColStd_Array1OfInteger* Mults,
0490 Point& P,
0491 Vector& V1,
0492 Vector& V2)
0493 {
0494 Standard_Integer dim,index = Index;
0495 Standard_Real u = U;
0496 Standard_Boolean rational;
0497 BSplCLib_DataContainer dc(Degree);
0498 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
0499 BSplCLib::Bohm(u,Degree,2,*dc.knots,dim,*dc.poles);
0500 Standard_Real *result = dc.poles;
0501 if (rational) {
0502 PLib::RationalDerivative(Degree,2,Dimension_gen,*dc.poles,*dc.ders);
0503 result = dc.ders;
0504 }
0505
0506 CoordsToPoint (P, result, );
0507 CoordsToPoint (V1, result + Dimension_gen, );
0508 if (!rational && (Degree < 2))
0509 NullifyPoint (V2);
0510 else
0511 CoordsToPoint (V2, result + 2 * Dimension_gen, );
0512 }
0513
0514 //=======================================================================
0515 //function : D3
0516 //purpose :
0517 //=======================================================================
0518
0519 void BSplCLib::D3
0520 (const Standard_Real U,
0521 const Standard_Integer Index,
0522 const Standard_Integer Degree,
0523 const Standard_Boolean Periodic,
0524 const Array1OfPoints& Poles,
0525 const TColStd_Array1OfReal* Weights,
0526 const TColStd_Array1OfReal& Knots,
0527 const TColStd_Array1OfInteger* Mults,
0528 Point& P,
0529 Vector& V1,
0530 Vector& V2,
0531 Vector& V3)
0532 {
0533 Standard_Integer dim,index = Index;
0534 Standard_Real u = U;
0535 Standard_Boolean rational;
0536 BSplCLib_DataContainer dc(Degree);
0537 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
0538 BSplCLib::Bohm(u,Degree,3,*dc.knots,dim,*dc.poles);
0539 Standard_Real *result = dc.poles;
0540 if (rational) {
0541 PLib::RationalDerivative(Degree,3,Dimension_gen,*dc.poles,*dc.ders);
0542 result = dc.ders;
0543 }
0544
0545 CoordsToPoint (P, result, );
0546 CoordsToPoint (V1, result + Dimension_gen, );
0547 if (!rational && (Degree < 2))
0548 NullifyPoint (V2);
0549 else
0550 CoordsToPoint (V2, result + 2 * Dimension_gen, );
0551 if (!rational && (Degree < 3))
0552 NullifyPoint (V3);
0553 else
0554 CoordsToPoint (V3, result + 3 * Dimension_gen, );
0555 }
0556
0557 //=======================================================================
0558 //function : DN
0559 //purpose :
0560 //=======================================================================
0561
0562 void BSplCLib::DN
0563 (const Standard_Real U,
0564 const Standard_Integer N,
0565 const Standard_Integer Index,
0566 const Standard_Integer Degree,
0567 const Standard_Boolean Periodic,
0568 const Array1OfPoints& Poles,
0569 const TColStd_Array1OfReal* Weights,
0570 const TColStd_Array1OfReal& Knots,
0571 const TColStd_Array1OfInteger* Mults,
0572 Vector& VN)
0573 {
0574 Standard_Integer dim,index = Index;
0575 Standard_Real u = U;
0576 Standard_Boolean rational;
0577 BSplCLib_DataContainer dc(Degree);
0578 PrepareEval(u,index,dim,rational,Degree,Periodic,Poles,Weights,Knots,Mults,dc);
0579 BSplCLib::Bohm(u,Degree,N,*dc.knots,dim,*dc.poles);
0580
0581 if (rational) {
0582 Standard_Real v[Dimension_gen];
0583 PLib::RationalDerivative(Degree,N,Dimension_gen,*dc.poles,v[0],Standard_False);
0584 CoordsToPoint (VN, v, );
0585 }
0586 else {
0587 if (N > Degree)
0588 NullifyPoint (VN);
0589 else {
0590 Standard_Real *DN = dc.poles + N * Dimension_gen;
0591 CoordsToPoint (VN, DN, );
0592 }
0593 }
0594 }
0595
0596 //=======================================================================
0597 //function : Solves a LU factored Matrix
0598 //purpose :
0599 //=======================================================================
0600
0601 Standard_Integer
0602 BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
0603 const Standard_Integer UpperBandWidth,
0604 const Standard_Integer LowerBandWidth,
0605 Array1OfPoints& PolesArray)
0606 {
0607 Standard_Real *PArray ;
0608 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
0609
0610 return BSplCLib::SolveBandedSystem(Matrix,
0611 UpperBandWidth,
0612 LowerBandWidth,
0613 Dimension_gen,
0614 PArray[0]) ;
0615 }
0616
0617 //=======================================================================
0618 //function : Solves a LU factored Matrix
0619 //purpose : if HomogeneousFlag is 1 then the input and the output
0620 // will be homogeneous that is no division or multiplication
0621 // by weigths will happen. On the contrary if HomogeneousFlag
0622 // is 0 then the poles will be multiplied first by the weights
0623 // and after interpolation they will be divided by the weights
0624 //=======================================================================
0625
0626 Standard_Integer
0627 BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
0628 const Standard_Integer UpperBandWidth,
0629 const Standard_Integer LowerBandWidth,
0630 const Standard_Boolean HomogeneousFlag,
0631 Array1OfPoints& PolesArray,
0632 TColStd_Array1OfReal& WeightsArray)
0633 {
0634 Standard_Real *PArray,
0635 * WArray ;
0636 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
0637 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
0638 return BSplCLib::SolveBandedSystem(Matrix,
0639 UpperBandWidth,
0640 LowerBandWidth,
0641 HomogeneousFlag,
0642 Dimension_gen,
0643 PArray[0],
0644 WArray[0]) ;
0645 }
0646
0647 //=======================================================================
0648 //function : Evaluates a Bspline function : uses the ExtrapMode
0649 //purpose : the function is extrapolated using the Taylor expansion
0650 // of degree ExtrapMode[0] to the left and the Taylor
0651 // expansion of degree ExtrapMode[1] to the right
0652 // if the HomogeneousFlag == True than the Poles are supposed
0653 // to be stored homogeneously and the result will also be homogeneous
0654 // Valid only if Weights
0655 //=======================================================================
0656 void BSplCLib::Eval(const Standard_Real Parameter,
0657 const Standard_Boolean PeriodicFlag,
0658 const Standard_Boolean HomogeneousFlag,
0659 Standard_Integer& ExtrapMode,
0660 const Standard_Integer Degree,
0661 const TColStd_Array1OfReal& FlatKnots,
0662 const Array1OfPoints& PolesArray,
0663 const TColStd_Array1OfReal& WeightsArray,
0664 Point& aPoint,
0665 Standard_Real& aWeight)
0666 {
0667 Standard_Real Inverse,
0668 P[Dimension_gen],
0669 *PArray,
0670 *WArray ;
0671 Standard_Integer kk ;
0672 PArray = (Standard_Real *) &PolesArray(PolesArray.Lower()) ;
0673 WArray = (Standard_Real *) &WeightsArray(WeightsArray.Lower()) ;
0674 if (HomogeneousFlag) {
0675 BSplCLib::Eval(Parameter,
0676 PeriodicFlag,
0677 0,
0678 ExtrapMode,
0679 Degree,
0680 FlatKnots,
0681 Dimension_gen,
0682 PArray[0],
0683 P[0]) ;
0684 BSplCLib::Eval(Parameter,
0685 PeriodicFlag,
0686 0,
0687 ExtrapMode,
0688 Degree,
0689 FlatKnots,
0690 1,
0691 WArray[0],
0692 aWeight) ;
0693 }
0694 else {
0695 BSplCLib::Eval(Parameter,
0696 PeriodicFlag,
0697 0,
0698 ExtrapMode,
0699 Degree,
0700 FlatKnots,
0701 Dimension_gen,
0702 PArray[0],
0703 WArray[0],
0704 P[0],
0705 aWeight) ;
0706 Inverse = 1.0e0 / aWeight ;
0707
0708 for (kk = 0 ; kk < Dimension_gen ; kk++) {
0709 P[kk] *= Inverse ;
0710 }
0711 }
0712
0713 for (kk = 0 ; kk < Dimension_gen ; kk++)
0714 aPoint.SetCoord(kk + 1, P[kk]) ;
0715 }
0716
0717 //=======================================================================
0718 //function : CacheD0
0719 //purpose : Evaluates the polynomial cache of the Bspline Curve
0720 //
0721 //=======================================================================
0722 void BSplCLib::CacheD0(const Standard_Real Parameter,
0723 const Standard_Integer Degree,
0724 const Standard_Real CacheParameter,
0725 const Standard_Real SpanLenght,
0726 const Array1OfPoints& PolesArray,
0727 const TColStd_Array1OfReal* WeightsArray,
0728 Point& aPoint)
0729 {
0730 //
0731 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
0732 // form
0733 // the SpanLenght is the normalizing factor so that the polynomial is between
0734 // 0 and 1
0735 Standard_Real NewParameter, Inverse;
0736 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
0737 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
0738 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
0739 PLib::NoDerivativeEvalPolynomial(NewParameter,
0740 Degree,
0741 Dimension_gen,
0742 Degree * Dimension_gen,
0743 PArray[0],
0744 myPoint[0]) ;
0745 if (WeightsArray != NULL) {
0746 const TColStd_Array1OfReal& refWeights = *WeightsArray;
0747 Standard_Real *
0748 WArray = (Standard_Real *) &refWeights(refWeights.Lower()) ;
0749 PLib::NoDerivativeEvalPolynomial(NewParameter,
0750 Degree,
0751 1,
0752 Degree,
0753 WArray[0],
0754 Inverse) ;
0755
0756 Inverse = 1.0e0 / Inverse;
0757 ModifyCoords (myPoint, *= Inverse);
0758 }
0759 }
0760
0761 //=======================================================================
0762 //function : CacheD1
0763 //purpose : Evaluates the polynomial cache of the Bspline Curve
0764 //
0765 //=======================================================================
0766 void BSplCLib::CacheD1(const Standard_Real Parameter,
0767 const Standard_Integer Degree,
0768 const Standard_Real CacheParameter,
0769 const Standard_Real SpanLenght,
0770 const Array1OfPoints& PolesArray,
0771 const TColStd_Array1OfReal* WeightsArray,
0772 Point& aPoint,
0773 Vector& aVector)
0774 {
0775 //
0776 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
0777 // form
0778 // the SpanLenght is the normalizing factor so that the polynomial is between
0779 // 0 and 1
0780 Standard_Real LocalPDerivatives[Dimension_gen << 1] ;
0781 // Standard_Real LocalWDerivatives[2], NewParameter, Inverse ;
0782 Standard_Real LocalWDerivatives[2], NewParameter ;
0783
0784 Standard_Real *
0785 PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
0786 Standard_Real *
0787 myPoint = (Standard_Real *) &aPoint ;
0788 Standard_Real *
0789 myVector = (Standard_Real *) &aVector ;
0790 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
0791 PLib::EvalPolynomial(NewParameter,
0792 1,
0793 Degree,
0794 Dimension_gen,
0795 PArray[0],
0796 LocalPDerivatives[0]) ;
0797 //
0798 // unormalize derivatives since those are computed normalized
0799 //
0800
0801 ModifyCoords (LocalPDerivatives + Dimension_gen, /= SpanLenght);
0802
0803 if (WeightsArray != NULL) {
0804 const TColStd_Array1OfReal& refWeights = *WeightsArray;
0805 Standard_Real *
0806 WArray = (Standard_Real *) &refWeights(refWeights.Lower()) ;
0807 PLib::EvalPolynomial(NewParameter,
0808 1,
0809 Degree,
0810 1,
0811 WArray[0],
0812 LocalWDerivatives[0]) ;
0813 //
0814 // unormalize the result since the polynomial stored in the cache
0815 // is normalized between 0 and 1
0816 //
0817 LocalWDerivatives[1] /= SpanLenght ;
0818
0819 PLib::RationalDerivatives(1,
0820 Dimension_gen,
0821 LocalPDerivatives[0],
0822 LocalWDerivatives[0],
0823 LocalPDerivatives[0]) ;
0824 }
0825
0826 CopyCoords (myPoint, LocalPDerivatives);
0827 CopyCoords (myVector, LocalPDerivatives + Dimension_gen);
0828 }
0829
0830 //=======================================================================
0831 //function : CacheD2
0832 //purpose : Evaluates the polynomial cache of the Bspline Curve
0833 //
0834 //=======================================================================
0835 void BSplCLib::CacheD2(const Standard_Real Parameter,
0836 const Standard_Integer Degree,
0837 const Standard_Real CacheParameter,
0838 const Standard_Real SpanLenght,
0839 const Array1OfPoints& PolesArray,
0840 const TColStd_Array1OfReal* WeightsArray,
0841 Point& aPoint,
0842 Vector& aVector1,
0843 Vector& aVector2)
0844 {
0845 //
0846 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
0847 // form
0848 // the SpanLenght is the normalizing factor so that the polynomial is between
0849 // 0 and 1
0850 Standard_Integer ii,Index,EndIndex;
0851 Standard_Real LocalPDerivatives[(Dimension_gen << 1) + Dimension_gen] ;
0852 // Standard_Real LocalWDerivatives[3], NewParameter, Factor, Inverse ;
0853 Standard_Real LocalWDerivatives[3], NewParameter, Factor ;
0854 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
0855 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
0856 Standard_Real * myVector1 = (Standard_Real *) &aVector1 ;
0857 Standard_Real * myVector2 = (Standard_Real *) &aVector2 ;
0858 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
0859 PLib::EvalPolynomial(NewParameter,
0860 2,
0861 Degree,
0862 Dimension_gen,
0863 PArray[0],
0864 LocalPDerivatives[0]) ;
0865 //
0866 // unormalize derivatives since those are computed normalized
0867 //
0868 Factor = 1.0e0/ SpanLenght ;
0869 Index = Dimension_gen ;
0870 EndIndex = Min (2, Degree) ;
0871
0872 for (ii = 1 ; ii <= EndIndex ; ii++) {
0873 ModifyCoords (LocalPDerivatives + Index, *= Factor);
0874 Factor /= SpanLenght ;
0875 Index += Dimension_gen;
0876 }
0877
0878 Index = (Degree + 1) * Dimension_gen;
0879 for (ii = Degree ; ii < 2 ; ii++) {
0880 NullifyCoords (LocalPDerivatives + Index);
0881 Index += Dimension_gen;
0882 }
0883
0884 if (WeightsArray != NULL) {
0885 const TColStd_Array1OfReal& refWeights = *WeightsArray;
0886 Standard_Real *
0887 WArray = (Standard_Real *) &refWeights(refWeights.Lower()) ;
0888
0889 PLib::EvalPolynomial(NewParameter,
0890 2,
0891 Degree,
0892 1,
0893 WArray[0],
0894 LocalWDerivatives[0]) ;
0895
0896 for (ii = Degree + 1 ; ii <= 2 ; ii++) {
0897 LocalWDerivatives[ii] = 0.0e0 ;
0898 }
0899 //
0900 // unormalize the result since the polynomial stored in the cache
0901 // is normalized between 0 and 1
0902 //
0903 Factor = 1.0e0 / SpanLenght ;
0904
0905 for (ii = 1 ; ii <= EndIndex ; ii++) {
0906 LocalWDerivatives[ii] *= Factor ;
0907 Factor /= SpanLenght ;
0908 }
0909 PLib::RationalDerivatives(2,
0910 Dimension_gen,
0911 LocalPDerivatives[0],
0912 LocalWDerivatives[0],
0913 LocalPDerivatives[0]) ;
0914 }
0915
0916 CopyCoords (myPoint, LocalPDerivatives);
0917 CopyCoords (myVector1, LocalPDerivatives + Dimension_gen);
0918 CopyCoords (myVector2, LocalPDerivatives + Dimension_gen * 2);
0919 }
0920
0921 //=======================================================================
0922 //function : CacheD3
0923 //purpose : Evaluates the polynomial cache of the Bspline Curve
0924 //
0925 //=======================================================================
0926 void BSplCLib::CacheD3(const Standard_Real Parameter,
0927 const Standard_Integer Degree,
0928 const Standard_Real CacheParameter,
0929 const Standard_Real SpanLenght,
0930 const Array1OfPoints& PolesArray,
0931 const TColStd_Array1OfReal* WeightsArray,
0932 Point& aPoint,
0933 Vector& aVector1,
0934 Vector& aVector2,
0935 Vector& aVector3)
0936 {
0937 //
0938 // the CacheParameter is where the cache polynomial was evaluated in homogeneous
0939 // form
0940 // the SpanLenght is the normalizing factor so that the polynomial is between
0941 // 0 and 1
0942 Standard_Integer ii, Index, EndIndex;
0943 Standard_Real LocalPDerivatives[Dimension_gen << 2] ;
0944 // Standard_Real LocalWDerivatives[4], Factor, NewParameter, Inverse ;
0945 Standard_Real LocalWDerivatives[4], Factor, NewParameter ;
0946 Standard_Real * PArray = (Standard_Real *) &(PolesArray(PolesArray.Lower())) ;
0947 Standard_Real * myPoint = (Standard_Real *) &aPoint ;
0948 Standard_Real * myVector1 = (Standard_Real *) &aVector1 ;
0949 Standard_Real * myVector2 = (Standard_Real *) &aVector2 ;
0950 Standard_Real * myVector3 = (Standard_Real *) &aVector3 ;
0951 NewParameter = (Parameter - CacheParameter) / SpanLenght ;
0952 PLib::EvalPolynomial(NewParameter,
0953 3,
0954 Degree,
0955 Dimension_gen,
0956 PArray[0],
0957 LocalPDerivatives[0]) ;
0958
0959 Index = (Degree + 1) * Dimension_gen;
0960 for (ii = Degree ; ii < 3 ; ii++) {
0961 NullifyCoords (LocalPDerivatives + Index);
0962 Index += Dimension_gen;
0963 }
0964
0965 //
0966 // unormalize derivatives since those are computed normalized
0967 //
0968 Factor = 1.0e0 / SpanLenght ;
0969 Index = Dimension_gen ;
0970 EndIndex = Min(3,Degree) ;
0971
0972 for (ii = 1 ; ii <= EndIndex ; ii++) {
0973 ModifyCoords (LocalPDerivatives + Index, *= Factor);
0974 Factor /= SpanLenght;
0975 Index += Dimension_gen;
0976 }
0977
0978 if (WeightsArray != NULL) {
0979 const TColStd_Array1OfReal& refWeights = *WeightsArray;
0980 Standard_Real *
0981 WArray = (Standard_Real *) &refWeights(refWeights.Lower()) ;
0982
0983 PLib::EvalPolynomial(NewParameter,
0984 3,
0985 Degree,
0986 1,
0987 WArray[0],
0988 LocalWDerivatives[0]) ;
0989 //
0990 // unormalize the result since the polynomial stored in the cache
0991 // is normalized between 0 and 1
0992 //
0993 Factor = 1.0e0 / SpanLenght ;
0994
0995 for (ii = 1 ; ii <= EndIndex ; ii++) {
0996 LocalWDerivatives[ii] *= Factor ;
0997 Factor /= SpanLenght ;
0998 }
0999
1000 for (ii = (Degree + 1) ; ii <= 3 ; ii++) {
1001 LocalWDerivatives[ii] = 0.0e0 ;
1002 }
1003 PLib::RationalDerivatives(3,
1004 Dimension_gen,
1005 LocalPDerivatives[0],
1006 LocalWDerivatives[0],
1007 LocalPDerivatives[0]) ;
1008 }
1009
1010 CopyCoords (myPoint, LocalPDerivatives);
1011 CopyCoords (myVector1, LocalPDerivatives + Dimension_gen);
1012 CopyCoords (myVector2, LocalPDerivatives + Dimension_gen * 2);
1013 CopyCoords (myVector3, LocalPDerivatives + Dimension_gen * 3);
1014 }
1015
1016 //=======================================================================
1017 //function : BuildCache
1018 //purpose : Stores theTaylor expansion normalized between 0,1 in the
1019 // Cache : in case of a rational function the Poles are
1020 // stored in homogeneous form
1021 //=======================================================================
1022
1023 void BSplCLib::BuildCache
1024 (const Standard_Real U,
1025 const Standard_Real SpanDomain,
1026 const Standard_Boolean Periodic,
1027 const Standard_Integer Degree,
1028 const TColStd_Array1OfReal& FlatKnots,
1029 const Array1OfPoints& Poles,
1030 const TColStd_Array1OfReal* Weights,
1031 Array1OfPoints& CachePoles,
1032 TColStd_Array1OfReal* CacheWeights)
1033 {
1034 Standard_Integer ii,
1035 Dimension,
1036 LocalIndex,
1037 index = 0 ;
1038 Standard_Real u = U,
1039 LocalValue ;
1040 Standard_Boolean rational;
1041
1042 BSplCLib_DataContainer dc(Degree);
1043 PrepareEval(u,
1044 index,
1045 Dimension,
1046 rational,
1047 Degree,
1048 Periodic,
1049 Poles,
1050 Weights,
1051 FlatKnots,
1052 (BSplCLib::NoMults()),
1053 dc);
1054 //
1055 // Watch out : PrepareEval checks if locally the Bspline is polynomial
1056 // therefore rational flag could be set to False even if there are
1057 // Weights. The Dimension is set accordingly.
1058 //
1059
1060 BSplCLib::Bohm(u,Degree,Degree,*dc.knots,Dimension,*dc.poles);
1061
1062 LocalValue = 1.0e0 ;
1063 LocalIndex = 0 ;
1064
1065 if (rational) {
1066
1067 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1068 CoordsToPoint (CachePoles(ii), dc.poles + LocalIndex, * LocalValue);
1069 LocalIndex += Dimension_gen + 1;
1070 LocalValue *= SpanDomain / (Standard_Real) ii ;
1071 }
1072
1073 LocalIndex = Dimension_gen;
1074 LocalValue = 1.0e0 ;
1075 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1076 (*CacheWeights)(ii) = dc.poles[LocalIndex] * LocalValue ;
1077 LocalIndex += Dimension_gen + 1;
1078 LocalValue *= SpanDomain / (Standard_Real) ii ;
1079 }
1080 }
1081 else {
1082
1083 for (ii = 1 ; ii <= Degree + 1 ; ii++) {
1084 CoordsToPoint (CachePoles(ii), dc.poles + LocalIndex, * LocalValue);
1085 LocalIndex += Dimension_gen;
1086 LocalValue *= SpanDomain / (Standard_Real) ii ;
1087 }
1088
1089 if (Weights != NULL) {
1090 for (ii = 1 ; ii <= Degree + 1 ; ii++)
1091 (*CacheWeights)(ii) = 0.0e0 ;
1092 (*CacheWeights)(1) = 1.0e0 ;
1093 }
1094 }
1095 }
1096
1097 void BSplCLib::BuildCache(const Standard_Real theParameter,
1098 const Standard_Real theSpanDomain,
1099 const Standard_Boolean thePeriodicFlag,
1100 const Standard_Integer theDegree,
1101 const Standard_Integer theSpanIndex,
1102 const TColStd_Array1OfReal& theFlatKnots,
1103 const Array1OfPoints& thePoles,
1104 const TColStd_Array1OfReal* theWeights,
1105 TColStd_Array2OfReal& theCacheArray)
1106 {
1107 Standard_Real aParam = theParameter;
1108 Standard_Integer anIndex = theSpanIndex;
1109 Standard_Integer aDimension;
1110 Standard_Boolean isRational;
1111
1112 BSplCLib_DataContainer dc(theDegree);
1113 PrepareEval(aParam,
1114 anIndex,
1115 aDimension,
1116 isRational,
1117 theDegree,
1118 thePeriodicFlag,
1119 thePoles,
1120 theWeights,
1121 theFlatKnots,
1122 (BSplCLib::NoMults()),
1123 dc);
1124 //
1125 // Watch out : PrepareEval checks if locally the Bspline is polynomial
1126 // therefore rational flag could be set to False even if there are
1127 // Weights. The Dimension is set accordingly.
1128 //
1129
1130 Standard_Integer aCacheShift = // helps to store weights when PrepareEval did not found that the curve is locally polynomial
1131 (theWeights != NULL && !isRational) ? aDimension + 1 : aDimension;
1132
1133 BSplCLib::Bohm(aParam, theDegree, theDegree, *dc.knots, aDimension, *dc.poles);
1134
1135 Standard_Real aCoeff = 1.0;
1136 Standard_Real* aCache = (Standard_Real *) &(theCacheArray(theCacheArray.LowerRow(), theCacheArray.LowerCol()));
1137 Standard_Real* aPolyCoeffs = dc.poles;
1138
1139 for (Standard_Integer i = 0; i <= theDegree; i++)
1140 {
1141 for (Standard_Integer j = 0; j< aDimension; j++)
1142 aCache[j] = aPolyCoeffs[j] * aCoeff;
1143 aCoeff *= theSpanDomain / (i+1);
1144 aPolyCoeffs += aDimension;
1145 aCache += aDimension;
1146 if (aCacheShift > aDimension)
1147 {
1148 aCache[0] = 0.0;
1149 aCache++;
1150 }
1151 }
1152
1153 if (aCacheShift > aDimension)
1154 theCacheArray.SetValue(theCacheArray.LowerRow(), theCacheArray.LowerCol() + aCacheShift - 1, 1.0);
1155 }
1156
1157 //=======================================================================
1158 //function : Interpolate
1159 //purpose :
1160 //=======================================================================
1161
1162 void BSplCLib::Interpolate(const Standard_Integer Degree,
1163 const TColStd_Array1OfReal& FlatKnots,
1164 const TColStd_Array1OfReal& Parameters,
1165 const TColStd_Array1OfInteger& ContactOrderArray,
1166 Array1OfPoints& Poles,
1167 Standard_Integer& InversionProblem)
1168
1169 {
1170 Standard_Real *PArray ;
1171
1172 PArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1173
1174 BSplCLib::Interpolate(Degree,
1175 FlatKnots,
1176 Parameters,
1177 ContactOrderArray,
1178 Dimension_gen,
1179 PArray[0],
1180 InversionProblem) ;
1181 }
1182
1183 //=======================================================================
1184 //function : Interpolate
1185 //purpose :
1186 //=======================================================================
1187
1188 void BSplCLib::Interpolate(const Standard_Integer Degree,
1189 const TColStd_Array1OfReal& FlatKnots,
1190 const TColStd_Array1OfReal& Parameters,
1191 const TColStd_Array1OfInteger& ContactOrderArray,
1192 Array1OfPoints& Poles,
1193 TColStd_Array1OfReal& Weights,
1194 Standard_Integer& InversionProblem)
1195 {
1196 Standard_Real *PArray,
1197 * WArray ;
1198 PArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1199 WArray = (Standard_Real *) &Weights(Weights.Lower()) ;
1200 BSplCLib::Interpolate(Degree,
1201 FlatKnots,
1202 Parameters,
1203 ContactOrderArray,
1204 Dimension_gen,
1205 PArray[0],
1206 WArray[0],
1207 InversionProblem) ;
1208 }
1209
1210 //=======================================================================
1211 //function : MovePoint
1212 //purpose : Find the new poles which allows an old point (with a
1213 // given u as parameter) to reach a new position
1214 //=======================================================================
1215
1216 void BSplCLib::MovePoint (const Standard_Real U,
1217 const Vector& Displ,
1218 const Standard_Integer Index1,
1219 const Standard_Integer Index2,
1220 const Standard_Integer Degree,
1221 const Array1OfPoints& Poles,
1222 const TColStd_Array1OfReal* Weights,
1223 const TColStd_Array1OfReal& FlatKnots,
1224 Standard_Integer& FirstIndex,
1225 Standard_Integer& LastIndex,
1226 Array1OfPoints& NewPoles)
1227 {
1228 // calculate the BSplineBasis in the parameter U
1229 Standard_Integer FirstNonZeroBsplineIndex;
1230 math_Matrix BSplineBasis(1, 1,
1231 1, Degree+1);
1232 Standard_Integer ErrorCode =
1233 BSplCLib::EvalBsplineBasis(0,
1234 Degree+1,
1235 FlatKnots,
1236 U,
1237 FirstNonZeroBsplineIndex,
1238 BSplineBasis);
1239 if (ErrorCode != 0) {
1240 FirstIndex = 0;
1241 LastIndex = 0;
1242
1243 for (Standard_Integer i=Poles.Lower(); i<=Poles.Upper(); i++) {
1244 NewPoles(i) = Poles(i);
1245 }
1246 return;
1247 }
1248
1249 // find the span which is predominant for parameter U
1250 FirstIndex = FirstNonZeroBsplineIndex;
1251 LastIndex = FirstNonZeroBsplineIndex + Degree ;
1252 if (FirstIndex < Index1) FirstIndex = Index1;
1253 if (LastIndex > Index2) LastIndex = Index2;
1254
1255 Standard_Real maxValue = 0.0;
1256 Standard_Integer i, kk1=0, kk2, ii;
1257
1258 for (i = FirstIndex-FirstNonZeroBsplineIndex+1;
1259 i <= LastIndex-FirstNonZeroBsplineIndex+1; i++) {
1260 if (BSplineBasis(1,i) > maxValue) {
1261 kk1 = i + FirstNonZeroBsplineIndex - 1;
1262 maxValue = BSplineBasis(1,i);
1263 }
1264 }
1265
1266 // find a kk2 if symetriy
1267 kk2 = kk1;
1268 i = kk1 - FirstNonZeroBsplineIndex + 2;
1269 if ((kk1+1) <= LastIndex) {
1270 if (Abs(BSplineBasis(1, kk1-FirstNonZeroBsplineIndex+2) - maxValue) < 1.e-10) {
1271 kk2 = kk1+1;
1272 }
1273 }
1274
1275 // compute the vector of displacement
1276 Standard_Real D1 = 0.0;
1277 Standard_Real D2 = 0.0;
1278 Standard_Real hN, Coef, Dval;
1279
1280 for (i = 1; i <= Degree+1; i++) {
1281 ii = i + FirstNonZeroBsplineIndex - 1;
1282 if (Weights != NULL) {
1283 hN = Weights->Value(ii)*BSplineBasis(1, i);
1284 D2 += hN;
1285 }
1286 else {
1287 hN = BSplineBasis(1, i);
1288 }
1289 if (ii >= FirstIndex && ii <= LastIndex) {
1290 if (ii < kk1) {
1291 Dval = kk1-ii;
1292 }
1293 else if (ii > kk2) {
1294 Dval = ii - kk2;
1295 }
1296 else {
1297 Dval = 0.0;
1298 }
1299 D1 += 1./(Dval + 1.) * hN;
1300 }
1301 }
1302
1303 if (Weights != NULL) {
1304 Coef = D2/D1;
1305 }
1306 else {
1307 Coef = 1./D1;
1308 }
1309
1310 // compute the new poles
1311
1312 for (i=Poles.Lower(); i<=Poles.Upper(); i++) {
1313 if (i >= FirstIndex && i <= LastIndex) {
1314 if (i < kk1) {
1315 Dval = kk1-i;
1316 }
1317 else if (i > kk2) {
1318 Dval = i - kk2;
1319 }
1320 else {
1321 Dval = 0.0;
1322 }
1323 NewPoles(i) = Poles(i).Translated((Coef/(Dval+1.))*Displ);
1324 }
1325 else {
1326 NewPoles(i) = Poles(i);
1327 }
1328 }
1329 }
1330
1331 //=======================================================================
1332 //function : MovePoint
1333 //purpose : Find the new poles which allows an old point (with a
1334 // given u as parameter) to reach a new position
1335 //=======================================================================
1336
1337 //=======================================================================
1338 //function : MovePointAndTangent
1339 //purpose :
1340 //=======================================================================
1341
1342 void BSplCLib::MovePointAndTangent (const Standard_Real U,
1343 const Vector& Delta,
1344 const Vector& DeltaDerivatives,
1345 const Standard_Real Tolerance,
1346 const Standard_Integer Degree,
1347 const Standard_Integer StartingCondition,
1348 const Standard_Integer EndingCondition,
1349 const Array1OfPoints& Poles,
1350 const TColStd_Array1OfReal* Weights,
1351 const TColStd_Array1OfReal& FlatKnots,
1352 Array1OfPoints& NewPoles,
1353 Standard_Integer & ErrorStatus)
1354 {
1355 Standard_Real *delta_array,
1356 *delta_derivative_array,
1357 *poles_array,
1358 *new_poles_array ;
1359
1360 Standard_Integer num_poles ;
1361 num_poles = Poles.Length() ;
1362
1363 if (NewPoles.Length() != num_poles) {
1364 throw Standard_ConstructionError();
1365 }
1366 delta_array = (Standard_Real *) &Delta ;
1367 delta_derivative_array = (Standard_Real *)&DeltaDerivatives ;
1368 poles_array = (Standard_Real *) &Poles(Poles.Lower()) ;
1369
1370 new_poles_array = (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1371 MovePointAndTangent(U,
1372 Dimension_gen,
1373 delta_array[0],
1374 delta_derivative_array[0],
1375 Tolerance,
1376 Degree,
1377 StartingCondition,
1378 EndingCondition,
1379 poles_array[0],
1380 Weights,
1381 FlatKnots,
1382 new_poles_array[0],
1383 ErrorStatus) ;
1384 }
1385
1386 //=======================================================================
1387 //function : Resolution
1388 //purpose :
1389 //=======================================================================
1390
1391 void BSplCLib::Resolution(const Array1OfPoints& Poles,
1392 const TColStd_Array1OfReal* Weights,
1393 const Standard_Integer NumPoles,
1394 const TColStd_Array1OfReal& FlatKnots,
1395 const Standard_Integer Degree,
1396 const Standard_Real Tolerance3D,
1397 Standard_Real& UTolerance)
1398 {
1399 Standard_Real *PolesArray ;
1400 PolesArray = (Standard_Real *) &Poles(Poles.Lower()) ;
1401 BSplCLib::Resolution(PolesArray[0],
1402 Dimension_gen,
1403 NumPoles,
1404 Weights,
1405 FlatKnots,
1406 Degree,
1407 Tolerance3D,
1408 UTolerance) ;
1409 }
1410
1411 //=======================================================================
1412 //function : FunctionMultiply
1413 //purpose :
1414 //=======================================================================
1415
1416 void BSplCLib::FunctionMultiply
1417 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1418 const Standard_Integer BSplineDegree,
1419 const TColStd_Array1OfReal & BSplineFlatKnots,
1420 const Array1OfPoints & Poles,
1421 const TColStd_Array1OfReal & FlatKnots,
1422 const Standard_Integer NewDegree,
1423 Array1OfPoints & NewPoles,
1424 Standard_Integer & theStatus)
1425 {
1426 Standard_Integer num_bspline_poles =
1427 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1428 Standard_Integer num_new_poles =
1429 FlatKnots.Length() - NewDegree - 1 ;
1430
1431 if (Poles.Length() != num_bspline_poles ||
1432 NewPoles.Length() != num_new_poles) {
1433 throw Standard_ConstructionError();
1434 }
1435 Standard_Real * array_of_poles =
1436 (Standard_Real *) &Poles(Poles.Lower()) ;
1437 Standard_Real * array_of_new_poles =
1438 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1439 BSplCLib::FunctionMultiply(FunctionPtr,
1440 BSplineDegree,
1441 BSplineFlatKnots,
1442 Dimension_gen,
1443 array_of_poles[0],
1444 FlatKnots,
1445 NewDegree,
1446 array_of_new_poles[0],
1447 theStatus);
1448 }
1449
1450 //=======================================================================
1451 //function : FunctionReparameterise
1452 //purpose :
1453 //=======================================================================
1454
1455 void BSplCLib::FunctionReparameterise
1456 (const BSplCLib_EvaluatorFunction & FunctionPtr,
1457 const Standard_Integer BSplineDegree,
1458 const TColStd_Array1OfReal & BSplineFlatKnots,
1459 const Array1OfPoints & Poles,
1460 const TColStd_Array1OfReal & FlatKnots,
1461 const Standard_Integer NewDegree,
1462 Array1OfPoints & NewPoles,
1463 Standard_Integer & theStatus)
1464 {
1465 Standard_Integer num_bspline_poles =
1466 BSplineFlatKnots.Length() - BSplineDegree - 1 ;
1467 Standard_Integer num_new_poles =
1468 FlatKnots.Length() - NewDegree - 1 ;
1469
1470 if (Poles.Length() != num_bspline_poles ||
1471 NewPoles.Length() != num_new_poles) {
1472 throw Standard_ConstructionError();
1473 }
1474 Standard_Real * array_of_poles =
1475 (Standard_Real *) &Poles(Poles.Lower()) ;
1476 Standard_Real * array_of_new_poles =
1477 (Standard_Real *) &NewPoles(NewPoles.Lower()) ;
1478 BSplCLib::FunctionReparameterise(FunctionPtr,
1479 BSplineDegree,
1480 BSplineFlatKnots,
1481 Dimension_gen,
1482 array_of_poles[0],
1483 FlatKnots,
1484 NewDegree,
1485 array_of_new_poles[0],
1486 theStatus);
1487 }