/// <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)); }