void BSplineBasis2D::computeLocalBasisFunctionsAndDerivatives(double* _basisFctsAndDerivs, int _derivDegree, double _uPrm, int _KnotSpanIndexU, double _vPrm, int _KnotSpanIndexV) { /* * Sorting idea for the 2D B-Spline basis functions * * eta * | * | CP(1,m) --> (m-1)*n+1 CP(2,m) --> (m-1)*n+2 ... CP(n,m) --> n*m * | * | ... ... ... ... * | * | CP(1,2) --> n+1 CP(2,2) --> n+2 ... CP(n,2) --> 2*n * | * | CP(1,1) --> 1 CP(2,1) --> 2 ... CP(n,1) --> n * |_______________________________________________________________________________xi * * On the input/output array _basisFctsAndDerivs: * _____________________________________________ * * · The functional values are sorted in a 3D dimensional array which is in turned sorted in an 1D pointer array: * _basisFctsAndDerivs = new double[(_derivDegree + 1) * (_derivDegree + 2) * noBasisFcts / 2] * computing all the partial derivatives in u-direction k-th and in v-direction l-th as 0 <= k + l <= _derivDegree * * · The element _basisFctsAndDerivs[basisIndex] where index = indexDerivativeBasisFunction(_derivDegree,i,j,k) of the output array * returns the i-th derivative with respect to u and the j-th derivative with respect to v (in total i+j-th partial derivative) * of the k-th B-Spline basis function N_(k) sorted as in the above table * * Reference: Piegl, Les and Tiller, Wayne, The NURBS Book. Springer-Verlag: Berlin 1995; p. 115. * _________ * * It is also assumed that there are n basis functions in u-direction and m basis functions in v-direction and additionally that the highest derivative in * u-direction is k-th order and in v-direction l-th order. */ // Read input assert(_basisFctsAndDerivs!=NULL); // Get the polynomial degrees of the basis int pDegree = uBSplineBasis1D->getPolynomialDegree(); int qDegree = vBSplineBasis1D->getPolynomialDegree(); // Find the number of basis functions which affect the current knot span int noBasisFcts = (pDegree + 1) * (qDegree + 1); // Initialize the index of the functional values into the 1D pointer array int index = 0; // Compute the derivatives of the local B-Spline basis functions in u-direction double* uBSplinebasis1DFctsDerivs = new double[(_derivDegree + 1) * (pDegree + 1)]; uBSplineBasis1D->computeLocalBasisFunctionsAndDerivatives(uBSplinebasis1DFctsDerivs, _derivDegree, _uPrm, _KnotSpanIndexU); // Compute the derivatives of the local B-Spline basis functions in v-direction double* vBSplinebasis1DFctsDerivs = new double[(_derivDegree + 1) * (qDegree + 1)]; vBSplineBasis1D->computeLocalBasisFunctionsAndDerivatives(vBSplinebasis1DFctsDerivs, _derivDegree, _vPrm, _KnotSpanIndexV); // Find the minimum between the derivative order and the polynomial degree in u-direction and store zeros for computational efficiency int du = min(_derivDegree, pDegree); // Loop over all the basis functions, over all derivatives in u-direction and then over all involved derivatives in v-direction for (int i = 0; i < noBasisFcts; i++) for (int k = pDegree + 1; k <= _derivDegree; k++) for (int l = 0; l <= _derivDegree - k; l++) { // Compute the index of the functional value index = indexDerivativeBasisFunction(_derivDegree, k, l, i); // Assign the value to zero _basisFctsAndDerivs[index] = 0.0; } // Find the minimum between the derivative order and the polynomial degree in v-direction and store zeros for computational efficiency int dv = min(_derivDegree, qDegree); // Loop over all the basis functions, over all derivatives in u-direction and then over all involved derivatives in v-direction for (int i = 0; i < noBasisFcts; i++) for (int l = qDegree + 1; l <= _derivDegree; l++) for (int k = 0; k <= _derivDegree - l; k++) { // Compute the index of the functional value index = indexDerivativeBasisFunction(_derivDegree, k, l, i); // Assign the value to zero _basisFctsAndDerivs[index] = 0.0; } // Initialize auxiliary variables int dd = 0; int counterBasis = 0; for (int vBasis = 0; vBasis <= qDegree; vBasis++) { for (int uBasis = 0; uBasis <= pDegree; uBasis++) { for (int k = 0; k <= du; k++) { dd = min(_derivDegree - k, dv); for (int l = 0; l <= dd; l++) { // Compute the index of the functional value index = indexDerivativeBasisFunction(_derivDegree, k, l, counterBasis); // Compute the functional value in 2D as a tensor product of the basis functions in 1D _basisFctsAndDerivs[index] = uBSplinebasis1DFctsDerivs[k * (pDegree + 1) + uBasis] * vBSplinebasis1DFctsDerivs[l * (qDegree + 1) + vBasis]; } } // Update the counter of the 2D B-Spline basis function counterBasis++; } } // Free the memory from the heap delete[] uBSplinebasis1DFctsDerivs; delete[] vBSplinebasis1DFctsDerivs; }
void NurbsBasis2D::computeLocalBasisFunctionsAndDerivatives(double* _basisFctsAndDerivs, int _derivDegree, double _uPrm, int _KnotSpanIndexU, double _vPrm, int _KnotSpanIndexV) { /* * Computes the NURBS basis functions and their derivatives at (_uPrm,_vPrm) surface parameters and stores them into the * input/output array _basisFctsAndDerivs. * * Sorting idea for the 2D NURBS basis functions: * * eta * | * | CP(1,m) --> (m-1)*n+1 CP(2,m) --> (m-1)*n+2 ... CP(n,m) --> n*m * | * | ... ... ... ... * | * | CP(1,2) --> n+1 CP(2,2) --> n+2 ... CP(n,2) --> 2*n * | * | CP(1,1) --> 1 CP(2,1) --> 2 ... CP(n,1) --> n * |_______________________________________________________________________________xi * * On the input/output array _basisFctsAndDerivs: * _____________________________________________ * * · The functional values are sorted in a 3 dimensional array which is in turned sorted in an 1D pointer array: * _basisFctsAndDerivs = new double[(_derivDegree + 1) * (_derivDegree + 1) * noBasisFcts] * computing all the partial derivatives in u-direction k-th and in v-direction l-th as 0 <= k + l <= _derivDegree * * · The element _bSplineBasisFctsAndDerivs[index] where index = indexDerivativeBasisFunction(_derivDegree,i,j,k) of the output array * returns the i-th derivative with respect to u and the j-th derivative with respect to v (in total i+j-th partial derivative) * of the k-th basis B-Spline basis function N_(k) sorted as in the above table * * Reference: Piegl, Les and Tiller, Wayne, The NURBS Book. Springer-Verlag: Berlin 1995; p. 137. * _________ * * It is also assumed that there are n basis functions in u-direction and m basis functions in v-direction. */ // Read input assert(_basisFctsAndDerivs!=NULL); // Get the polynomial degrees int pDegree = getUBSplineBasis1D()->getPolynomialDegree(); int qDegree = getVBSplineBasis1D()->getPolynomialDegree(); // The number of the basis functions int noBasisFcts = (pDegree + 1) * (qDegree + 1); // Initialize the index of the basis int indexBSplineBasis = 0; int indexNurbsBasis = 0; // Initialize the output array to zero for (int i = 0; i <= _derivDegree; i++) for (int j = 0; j <= _derivDegree - i; j++) for (int k = 0; k < noBasisFcts; k++) { // Compute the index of the basis indexNurbsBasis = indexDerivativeBasisFunction(_derivDegree, i, j, k); // Initialize the B-Spline basis function value _basisFctsAndDerivs[indexNurbsBasis] = 0.0; } // Compute the B-Spline basis functions and their partial derivatives up to _derivDegree absolute order double* bSplineBasisFctAndDeriv = new double[(_derivDegree + 1) * (_derivDegree + 2) * noBasisFcts / 2]; BSplineBasis2D::computeLocalBasisFunctionsAndDerivatives(bSplineBasisFctAndDeriv, _derivDegree, _uPrm, _KnotSpanIndexU, _vPrm, _KnotSpanIndexV); // Initialize the counter of the basis functions int counterBasis = 0; // Initialize the index the Control Point weights int uIndexCP = 0; int vIndexCP = 0; // Compute the denominator function double* denominatorFct = new double[(_derivDegree + 1) * (_derivDegree + 1)]; computeDenominatorFunctionAndDerivatives(denominatorFct, bSplineBasisFctAndDeriv, _derivDegree, _KnotSpanIndexU, _KnotSpanIndexV); // Initialize auxiliary variables double v = 0.0; double v2 = 0.0; // Reset basis function counter to zero counterBasis = 0; // Loop over all the basis functions in v-direction for (int vBasis = 0; vBasis <= qDegree; vBasis++) { // Loop over all the basis functions in u-direction for (int uBasis = 0; uBasis <= pDegree; uBasis++) { // Loop over all the derivatives in u-direction for (int k = 0; k <= _derivDegree; k++) { // Loop over all the derivatives in v-direction for (int l = 0; l <= _derivDegree - k; l++) { // Compute the B-Spline basis function index indexBSplineBasis = indexDerivativeBasisFunction(_derivDegree, k, l, counterBasis); // Compute the Control Point indices uIndexCP = _KnotSpanIndexU - pDegree + uBasis; vIndexCP = _KnotSpanIndexV - qDegree + vBasis; // Store temporary value v = bSplineBasisFctAndDeriv[indexBSplineBasis] * IGAControlPointWeights[vIndexCP * uNoBasisFnc + uIndexCP]; for (int j = 1; j <= l; j++) { // Compute the NURBS basis function index indexNurbsBasis = indexDerivativeBasisFunction(_derivDegree, k, l - j, counterBasis); // Update the scalar value v -= EMPIRE::MathLibrary::binomialCoefficients[GETINDEX(l, j)] * denominatorFct[j * (_derivDegree + 1)] * _basisFctsAndDerivs[indexNurbsBasis]; } for (int i = 1; i <= k; i++) { // Compute the NURBS basis function index indexNurbsBasis = indexDerivativeBasisFunction(_derivDegree, k - i, l, counterBasis); // Update the scalar value v -= EMPIRE::MathLibrary::binomialCoefficients[GETINDEX(k, i)] * denominatorFct[i] * _basisFctsAndDerivs[indexNurbsBasis]; v2 = 0.0; for (int j = 1; j <= l; j++) { // Compute the NURBS basis function index indexNurbsBasis = indexDerivativeBasisFunction(_derivDegree, k - i, l - j, counterBasis); // Update the scalar value v2 += EMPIRE::MathLibrary::binomialCoefficients[GETINDEX(l, j)] * denominatorFct[j * (_derivDegree + 1) + i] * _basisFctsAndDerivs[indexNurbsBasis]; } v -= EMPIRE::MathLibrary::binomialCoefficients[GETINDEX(k, i)] * v2; } // Compute the NURBS basis function index indexNurbsBasis = indexDerivativeBasisFunction(_derivDegree, k, l, counterBasis); // Update the value of the basis function derivatives _basisFctsAndDerivs[indexNurbsBasis] = v / denominatorFct[0]; } } // Update basis function's counter counterBasis++; } } // Free the memory from the heap delete[] bSplineBasisFctAndDeriv; delete[] denominatorFct; }