/// <summary> /// Determines the derivatives of a curve at a given parameter.<br/> /// <em>Corresponds to algorithm 3.2 from The NURBS Book by Piegl and Tiller.</em> /// </summary> /// <param name="curve">The curve object.</param> /// <param name="parameter">Parameter on the curve at which the point is to be evaluated.</param> /// <param name="numberDerivs">Integer number of basis functions - 1 = knots.length - degree - 2.</param> /// <returns>The derivatives.</returns> internal static List <Point4> CurveDerivatives(NurbsBase curve, double parameter, int numberDerivs) { List <Point4> curveHomogenizedPoints = curve.ControlPoints; int n = curve.Knots.Count - curve.Degree - 2; int derivateOrder = numberDerivs < curve.Degree ? numberDerivs : curve.Degree; Point4[] ck = new Point4[numberDerivs + 1]; int knotSpan = curve.Knots.Span(n, curve.Degree, parameter); List <Vector> derived2d = DerivativeBasisFunctionsGivenNI(knotSpan, parameter, curve.Degree, derivateOrder, curve.Knots); for (int k = 0; k < derivateOrder + 1; k++) { for (int j = 0; j < curve.Degree + 1; j++) { double valToMultiply = derived2d[k][j]; Point4 pt = curveHomogenizedPoints[knotSpan - curve.Degree + j]; for (int i = 0; i < pt.Size; i++) { ck[k][i] = ck[k][i] + (valToMultiply * pt[i]); } } } return(ck.ToList()); }
/// <summary> /// Inserts a collection of knots on a curve.<br/> /// <em>Implementation of Algorithm A5.4 of The NURBS Book by Piegl and Tiller.</em> /// </summary> /// <param name="curve">The curve object.</param> /// <param name="knotsToInsert">The set of knots.</param> /// <returns>A curve with refined knots.</returns> internal static NurbsBase KnotRefine(NurbsBase curve, IList <double> knotsToInsert) { if (knotsToInsert.Count == 0) { return(curve); } int degree = curve.Degree; List <Point4> controlPoints = curve.ControlPoints; KnotVector knots = curve.Knots; // Initialize common variables. int n = controlPoints.Count - 1; int m = n + degree + 1; int r = knotsToInsert.Count - 1; int a = knots.Span(degree, knotsToInsert[0]); int b = knots.Span(degree, knotsToInsert[r]); Point4[] controlPointsPost = new Point4[n + r + 2]; double[] knotsPost = new double[m + r + 2]; // New control points. for (int i = 0; i < a - degree + 1; i++) { controlPointsPost[i] = controlPoints[i]; } for (int i = b - 1; i < n + 1; i++) { controlPointsPost[i + r + 1] = controlPoints[i]; } // New knot vector. for (int i = 0; i < a + 1; i++) { knotsPost[i] = knots[i]; } for (int i = b + degree; i < m + 1; i++) { knotsPost[i + r + 1] = knots[i]; } // Initialize variables for knot refinement. int g = b + degree - 1; int k = b + degree + r; int j = r; // Apply knot refinement. while (j >= 0) { while (knotsToInsert[j] <= knots[g] && g > a) { controlPointsPost[k - degree - 1] = controlPoints[g - degree - 1]; knotsPost[k] = knots[g]; --k; --g; } controlPointsPost[k - degree - 1] = controlPointsPost[k - degree]; for (int l = 1; l < degree + 1; l++) { int ind = k - degree + l; double alfa = knotsPost[k + l] - knotsToInsert[j]; if (Math.Abs(alfa) < GSharkMath.Epsilon) { controlPointsPost[ind - 1] = controlPointsPost[ind]; } else { alfa /= (knotsPost[k + l] - knots[g - degree + l]); controlPointsPost[ind - 1] = (controlPointsPost[ind - 1] * alfa) + (controlPointsPost[ind] * (1.0 - alfa)); } } knotsPost[k] = knotsToInsert[j]; --k; --j; } return(new NurbsCurve(degree, knotsPost.ToKnot(), controlPointsPost.ToList())); }