Example #1
0
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;
}
Example #2
0
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;
}