// Spit out an endless sequence of bezier segments along a normalized spiral (origo-centered, radius = angle) static IEnumerable <BezierSpiralSegment> GenerateBezierSpiralSegments(double startAngle, double angleStep) { var startPoint = PointOnSpiral.At(startAngle); while (true) { var endPoint = PointOnSpiral.At(startPoint.Angle + angleStep); var bezier = BezierSpiralSegment.ForSpiralSegment(startPoint, endPoint); startPoint = endPoint; yield return(bezier); } }
// Creates a BezierSpiralSegment between two points on the spiral. // Placement of control points is based on https://stackoverflow.com/a/27863181 public static BezierSpiralSegment ForSpiralSegment(PointOnSpiral p0, PointOnSpiral p3) { var cpOffset = 4 * Math.Tan((p3.Angle - p0.Angle) / 4) / 3; return(new BezierSpiralSegment { P0 = p0, P1 = new Point( x: Math.Cos(p0.TangentAngle) * cpOffset * p0.Angle + p0.Point.X, y: Math.Sin(p0.TangentAngle) * cpOffset * p0.Angle + p0.Point.Y), P2 = new Point( x: Math.Cos(p3.TangentAngle - Math.PI) * cpOffset * p3.Angle + p3.Point.X, y: Math.Sin(p3.TangentAngle - Math.PI) * cpOffset * p3.Angle + p3.Point.Y), P3 = p3, }); }