public static List <NurbsCurve> CurveSplit(NurbsCurve curve, double u) { int degree = curve.Degree; List <Vector> controlPoints = curve.ControlPoints; KnotArray knots = curve.Knots; List <double> knots_to_insert = new List <double>(); for (int i = 0; i <= degree; i++) { knots_to_insert.Add(u); } NurbsCurve refinedCurve = Modify.CurveKnotRefine(curve, knots_to_insert); int s = Eval.KnotSpan(degree, u, knots); KnotArray knots0 = (KnotArray)refinedCurve.Knots.ToList().GetRange(0, s + degree + 2); KnotArray knots1 = (KnotArray)refinedCurve.Knots.ToList().GetRange(0, s + 1); List <Vector> cpts0 = refinedCurve.ControlPoints.GetRange(0, s + 1); List <Vector> cpts1 = refinedCurve.ControlPoints.GetRange(0, s + 1); return(new List <NurbsCurve>() { new NurbsCurve(degree, knots0, cpts0), new NurbsCurve(degree, knots1, cpts1) }); }
/// <summary> /// Check whether a given list is a valid NURBS knot vector. This also checks the validity of the end points. /// More specifically, this method checks if the knot vector is of the following structure: /// The knot vector must be non-decreasing and of length (degree + 1) * 2 or greater /// [ (degree + 1 copies of the first knot), internal non-decreasing knots, (degree + 1 copies of the last knot) ] /// </summary> /// <param name="vector">The knot vector to test</param> /// <param name="degree">The degree</param> /// <returns>Whether the array is a valid knot vector or knot</returns> public static bool IsValidKnotVector(KnotArray vector, int degree) { if (vector.Count == 0) { return(false); } if (vector.Count < (degree + 1) * 2) { return(false); } var rep = vector.First(); for (int i = 0; i <= degree + 1; i++) { if (Math.Abs(vector[i] - rep) > Constants.EPSILON) { return(false); } } rep = vector.Last(); for (int i = vector.Count - degree - 1; i <= vector.Count; i++) { if (Math.Abs(vector[i] - rep) > Constants.EPSILON) { return(false); } } return(IsNonDecreasing(vector)); }
/// <summary> /// find the span on the knot list of the given parameter, (corresponds to algorithm 2.1 from the NURBS book, piegl & Tiller 2nd edition) /// /// </summary> /// <param name="n">integer number of basis functions - 1 = knots.length - degree - 2</param> /// <param name="degree">integer degree of function</param> /// <param name="u">parameter</param> /// <param name="knots">array of nondecreasing knot values</param> /// <returns>the index of the knot span</returns> public static int KnotSpanGivenN(int n, int degree, double u, KnotArray knots) { if (u > knots[n + 1] - Constants.EPSILON) { return(n); } if (u < knots[degree] + Constants.EPSILON) { return(degree); } var low = degree; var high = n + 1; int mid = (int)Math.Floor((decimal)(low + high) / 2); while (u < knots[mid] || u >= knots[mid + 1]) { if (u < knots[mid]) { high = mid; } else { low = mid; } mid = (int)Math.Floor((decimal)(low + high) / 2); } return(mid); }
public NurbsSurface(int degreeU, int degreeV, KnotArray knotsU, KnotArray knotsV, List <List <Point> > controlPoints) { DegreeU = degreeU; DegreeV = degreeV; KnotsU = knotsU; KnotsV = knotsV; ControlPoints = controlPoints; }
public Volume(int degreeU, int degreeV, int degreeW, KnotArray knotsU, KnotArray knotsV, KnotArray knotsW, List <List <List <Point> > > controlPoints) { DegreeU = degreeU; DegreeV = degreeV; DegreeW = degreeW; KnotsU = knotsU; KnotsV = knotsV; KnotsW = knotsW; ControlPoints = controlPoints; }
public static NurbsCurve Polyline(List <Vector> points) { KnotArray knots = new KnotArray() { 0.0, 0.0 }; double lsum = 0.0; for (int i = 0; i < points.Count - 1; i++) { lsum += Constants.DistanceTo(points[i], points[i + 1]); knots.Add(lsum); } knots.Add(lsum); var weights = points.Select(x => 1.0).ToList(); points.ForEach(x => weights.Add(1.0)); return(new NurbsCurve(1, knots, Eval.Homogenize1d(points, weights))); }
public static NurbsCurve RationalBezierCurve(List <Vector> controlPoints, List <double> weights = null) { var degree = controlPoints.Count - 1; var knots = new KnotArray(); for (int i = 0; i < degree + 1; i++) { knots.Add(0.0); } for (int i = 0; i < degree + 1; i++) { knots.Add(1.0); } if (weights == null) { weights = Sets.RepeatData(1.0, controlPoints.Count); } return(new NurbsCurve(degree, knots, Eval.Homogenize1d(controlPoints, weights))); weights = Constants.Rep(controlPoints.Count, 1.0); //return new NurbsCurveData(degree, knots, Eval.Homogenize1d(controlPoints, weights)); return(null); }
/// <summary> /// Insert a collectioin of knots on a curve /// corresponds to Algorithm A5.2 (Piegl & Tiller) /// </summary> /// <param name="curve"></param> /// <param name="knotsToInsert"></param> /// <returns></returns> public static NurbsCurve CurveKnotRefine(NurbsCurve curve, List <double> knotsToInsert) { if (knotsToInsert.Count == 0) { return(curve); } int degree = curve.Degree; List <Vector> controlPoints = curve.ControlPoints; KnotArray knots = curve.Knots; int n = controlPoints.Count - 1; int m = n + degree + 1; int r = knotsToInsert.Count - 1; int a = Eval.KnotSpan(degree, knotsToInsert[0], knots); int b = Eval.KnotSpan(degree, knotsToInsert[r], knots); List <Vector> controlPoints_post = new List <Vector>(); KnotArray knots_post = new KnotArray(); //new control points for (int i = 0; i <= a - degree; i++) { controlPoints_post[i] = controlPoints[i]; } for (int i = b - 1; i <= n; i++) { controlPoints_post[i + r + 1] = controlPoints[i]; } //new knot vector for (int i = 0; i <= a; i++) { knots_post[i] = knots[i]; } for (int i = b + degree; i <= m; i++) { knots_post[i + r + 1] = knots[i]; } int g = b + degree + 1; int k = b + degree + r; int j = r; while (j >= 0) { while (knotsToInsert[j] <= knots[g] && g > a) { controlPoints_post[k - degree - 1] = controlPoints[g - degree - 1]; knots_post[k] = knots[g]; k--; g--; } controlPoints_post[k - degree - 1] = controlPoints_post[k - degree]; for (int i = 1; i <= degree; i++) { int ind = k - degree + 1; double alfa = knots_post[k + 1] - knotsToInsert[j]; if (Math.Abs(alfa) < Constants.EPSILON) { controlPoints_post[ind - 1] = controlPoints_post[ind]; } else { alfa = alfa / (knots_post[k + 1] - knots[g - degree + 1]); controlPoints_post[ind - 1] = (Vector)Constants.Addition(Constants.Multiplication(controlPoints_post[ind - 1], alfa), Constants.Multiplication(controlPoints_post[ind], 1.0 - alfa)); } } knots_post[k] = knotsToInsert[j]; k = k - 1; j--; } return(new NurbsCurve(degree, knots_post, controlPoints_post)); }
/// <summary> /// Reverse a knot vector /// </summary> /// <param name="knots">An array of knots</param> /// <returns>The reversed array of knots</returns> public static KnotArray KnotsReverse(KnotArray knots) { throw new NotImplementedException(); }
public NurbsCurve(int degree, KnotArray knots, List <Vector> controlPoints) { Degree = degree; ControlPoints = controlPoints; Knots = knots; }
/// <summary> /// Find the span on the knot Array without supplying n /// </summary> /// <param name="degree">integer degree of function</param> /// <param name="u">float parameter</param> /// <param name="knots">array of nondecreasing knot values</param> /// <returns></returns> public static int KnotSpan(int degree, double u, KnotArray knots) { return(KnotSpanGivenN(knots.Count - degree - 2, degree, u, knots)); }