Example #1
0
        /// <summary>
        /// Computes the derivatives on a non-uniform, non-rational B-spline surface.<br/>
        /// SKL is the derivative S(u,v) with respect to U K-times and V L-times.<br/>
        /// <em>Corresponds to algorithm 3.6 from The NURBS Book by Piegl and Tiller.</em>
        /// </summary>
        /// <param name="surface">The surface.</param>
        /// <param name="u">The U parameter at which to evaluate the derivatives.</param>
        /// <param name="v">The V parameter at which to evaluate the derivatives.</param>
        /// <param name="numDerivs">Number of derivatives to evaluate, set as default to 1.</param>
        /// <returns>A tuple with 2D collection representing all derivatives(k,L) and weights(k,l): U derivatives increase by row, V by column.</returns>
        internal static Tuple <Vector3[, ], double[, ]> Derivatives(NurbsSurface surface, double u, double v, int numDerivs = 1)
        {
            // number of basis function.
            int n = surface.KnotsU.Count - surface.DegreeU - 2;
            int m = surface.KnotsV.Count - surface.DegreeV - 2;

            // number of derivatives.
            int du = Math.Min(numDerivs, surface.DegreeU);
            int dv = Math.Min(numDerivs, surface.DegreeV);

            int knotSpanU = surface.KnotsU.Span(n, surface.DegreeU, u);
            int knotSpanV = surface.KnotsV.Span(m, surface.DegreeV, v);

            List <Vector> uDerivs = Curve.DerivativeBasisFunctionsGivenNI(knotSpanU, u, surface.DegreeU, n, surface.KnotsU);
            List <Vector> vDerivs = Curve.DerivativeBasisFunctionsGivenNI(knotSpanV, v, surface.DegreeV, m, surface.KnotsV);

            int dim = surface.ControlPoints[0][0].Size;
            List <List <Vector> > SKLw = Vector.Zero3d(numDerivs + 1, numDerivs + 1, dim);
            List <Vector>         temp = Vector.Zero2d(surface.DegreeV + 1, dim);

            Vector3[,] SKL    = new Vector3[numDerivs + 1, numDerivs + 1];
            double[,] weights = new double[numDerivs + 1, numDerivs + 1];

            for (int k = 0; k < du + 1; k++)
            {
                for (int s = 0; s < surface.DegreeV + 1; s++)
                {
                    temp[s] = Vector.Zero1d(dim);
                    for (int r = 0; r < surface.DegreeU + 1; r++)
                    {
                        Vector.AddMulMutate(temp[s], uDerivs[k][r], surface.ControlPoints[knotSpanU - surface.DegreeU + r][knotSpanV - surface.DegreeV + s]);
                    }
                }

                int dd = Math.Min(numDerivs - k, dv);

                for (int l = 0; l < dd + 1; l++)
                {
                    SKLw[k][l] = Vector.Zero1d(dim);
                    for (int s = 0; s < surface.DegreeV + 1; s++)
                    {
                        Vector.AddMulMutate(SKLw[k][l], vDerivs[l][s], temp[s]);
                    }

                    SKL[k, l]     = new Vector3(SKLw[k][l][0], SKLw[k][l][1], SKLw[k][l][2]); // Extracting the derivatives.
                    weights[k, l] = SKLw[k][l][3];                                            // Extracting the weights.
                }
            }

            return(new Tuple <Vector3[, ], double[, ]>(SKL, weights));
        }