public static IEnumerable <PrimitiveBezier> SplineToBezierCurves(Spline spline) { if (spline == null) { throw new ArgumentNullException(nameof(spline)); } var expectedIdenticalKnots = spline.Degree + 1; var builder = new SplineBuilder(spline.Degree, spline.ControlPoints, spline.KnotValues); for (int offset = 0; ; offset++) { // get next set of values var values = builder.KnotValues.Skip(offset * expectedIdenticalKnots).Take(expectedIdenticalKnots).ToList(); if (values.Count == 0 && builder.KnotValues.Count() % expectedIdenticalKnots == 0) { // done break; } var expectedValue = values[0]; int missingValueCount; if (values.Count < expectedIdenticalKnots) { // not enough values missingValueCount = expectedIdenticalKnots - values.Count; } else if (values.Count < expectedIdenticalKnots || values.Any(v => v != expectedValue)) { // not all the same missingValueCount = expectedIdenticalKnots - values.Count(v => v == expectedValue); } else { missingValueCount = 0; } for (int i = 0; i < missingValueCount; i++) { builder.InsertKnot(expectedValue); } } var points = builder.ControlPoints.ToList(); var curves = new List <PrimitiveBezier>(); for (int startIndex = 0; startIndex < points.Count; startIndex += expectedIdenticalKnots) { var curve = PrimitiveBezier.FromPoints(points, startIndex, expectedIdenticalKnots); curves.Add(curve); } return(curves); }
public Spline(int degree, IEnumerable <Point> controlPoints, IEnumerable <double> knotValues, CadColor?color = null, object tag = null) : base(color, tag) { if (controlPoints == null) { throw new ArgumentNullException(nameof(controlPoints)); } if (knotValues == null) { throw new ArgumentNullException(nameof(knotValues)); } if (degree != 3) { throw new NotImplementedException("Only cubic splines are currently supported."); } Degree = degree; ControlPoints = controlPoints.ToArray(); KnotValues = knotValues.ToArray(); if (KnotValues.Length != ControlPoints.Length + Degree + 1) { throw new InvalidOperationException("The number of knot values must be one greater than the sum of the number of control points and the degree of the curve."); } _snapPoints = new[] { new EndPoint(ControlPoints[0]), new EndPoint(ControlPoints[ControlPoints.Length - 1]) }; _beziers = SplineBuilder.SplineToBezierCurves(this).ToArray(); BoundingBox = BoundingBox.Includes(_beziers.Select(b => b.GetBoundingBox())); }