public static bool CatmullRomSegmentToCurve4(this PathWriter _writer, double x0, double y0, //p0 //explicit x0 y0 double x1, double y1, //p1 double x2, double y2, //p2 double x3, double y3) //p3 { //just experiment only, //not correct now //https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline //https://stackoverflow.com/questions/30748316/catmull-rom-interpolation-on-svg-paths double t0 = 0.0f, t1 = CatmullRomGetT(t0, x0, y0, x1, y1), t2 = CatmullRomGetT(t1, x1, y1, x2, y2), t3 = CatmullRomGetT(t2, x2, y2, x3, y3); if ((t0 == t1) || (t1 == t2) || (t2 == t3)) { //invalid _writer.LineTo(x1, y1); _writer.LineTo(x2, y2); return(false); } double c1 = (t2 - t1) / (t2 - t0), c2 = (t1 - t0) / (t2 - t0), d1 = (t3 - t2) / (t3 - t1), d2 = (t2 - t1) / (t3 - t1); double m1x = (t2 - t1) * (c1 * (x1 - x0) / (t1 - t0) + c2 * (x2 - x1) / (t2 - t1)); double m2x = (t2 - t1) * (d1 * (x2 - x1) / (t2 - t1) + d2 * (x3 - x2) / (t3 - t2)); double m1y = (t2 - t1) * (c1 * (y1 - y0) / (t1 - t0) + c2 * (y2 - y1) / (t2 - t1)); double m2y = (t2 - t1) * (d1 * (y2 - y1) / (t2 - t1) + d2 * (y3 - y2) / (t3 - t2)); //Q0 = P1 //Q1 = P1 + M1 / 3 //Q2 = P2 - M2 / 3 //Q3 = P2 _writer.LineTo(x1, y1); _writer.Curve4(x1 + m1x / 3, y1 + m1y / 3, x2 - m2x / 3, y2 - m2y / 3, x2, y2); return(true); }
/// <summary> /// draw line /// </summary> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <param name="color"></param> public override void DrawLine(double x1, double y1, double x2, double y2) { //BitmapExt if (this.RenderQuality == RenderQualtity.Fast) { this._bxt.DrawLine( (int)Math.Round(x1), (int)Math.Round(y1), (int)Math.Round(x2), (int)Math.Round(y2), this.strokeColor.ToARGB() ); return; } //---------------------------------------------------------- //Agg if (_orientation == DrawBoardOrientation.LeftBottom) { //as original _lineGen.Clear(); _lineGen.MoveTo(x1, y1); _lineGen.LineTo(x2, y2); var v1 = GetFreeVxs(); _aggsx.Render(stroke.MakeVxs(_lineGen.Vxs, v1), this.strokeColor); ReleaseVxs(ref v1); } else { //left-top int h = this.Height; _lineGen.Clear(); _lineGen.MoveTo(x1, h - y1); _lineGen.LineTo(x2, h - y2); var v1 = GetFreeVxs(); _aggsx.Render(stroke.MakeVxs(_lineGen.Vxs, v1), this.strokeColor); ReleaseVxs(ref v1); } }
static void SplineCurveSegment( PathWriter writer, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, float tension) { //from SplineExtensions.cs //MIT, 2009-2015, Rene Schulte and WriteableBitmapEx Contributors, https://github.com/teichgraf/WriteableBitmapEx // // Project: WriteableBitmapEx - WriteableBitmap extensions // Description: Collection of draw spline extension methods for the WriteableBitmap class. // // Changed by: $Author: unknown $ // Changed on: $Date: 2015-03-05 18:18:24 +0100 (Do, 05 Mrz 2015) $ // Changed in: $Revision: 113191 $ // Project: $URL: https://writeablebitmapex.svn.codeplex.com/svn/trunk/Source/WriteableBitmapEx/WriteableBitmapSplineExtensions.cs $ // Id: $Id: WriteableBitmapSplineExtensions.cs 113191 2015-03-05 17:18:24Z unknown $ // // // Copyright © 2009-2015 Rene Schulte and WriteableBitmapEx Contributors // Determine distances between controls points (bounding rect) to find the optimal stepsize double minX = Math.Min(x1, Math.Min(x2, Math.Min(x3, x4))); double minY = Math.Min(y1, Math.Min(y2, Math.Min(y3, y4))); double maxX = Math.Max(x1, Math.Max(x2, Math.Max(x3, x4))); double maxY = Math.Max(y1, Math.Max(y2, Math.Max(y3, y4))); // Get slope double lenx = maxX - minX; double len = maxY - minY; if (lenx > len) { len = lenx; } // Prevent division by zero if (len != 0) { // Init vars double step = STEP_FACTOR / len; double tx1 = x2; double ty1 = y2; // Calculate factors double sx1 = tension * (x3 - x1); double sy1 = tension * (y3 - y1); double sx2 = tension * (x4 - x2); double sy2 = tension * (y4 - y2); double ax = sx1 + sx2 + 2 * x2 - 2 * x3; double ay = sy1 + sy2 + 2 * y2 - 2 * y3; double bx = -2 * sx1 - sx2 - 3 * x2 + 3 * x3; double by = -2 * sy1 - sy2 - 3 * y2 + 3 * y3; // Interpolate writer.LineTo(tx1, ty1); double tx2, ty2; for (double t = step; t <= 1; t += step) { double tSq = t * t; tx2 = (ax * tSq * t + bx * tSq + sx1 * t + x2); ty2 = (ay * tSq * t + by * tSq + sy1 * t + y2); // Draw line // //DrawLine(context, w, h, tx1, ty1, tx2, ty2, color); writer.LineTo(tx2, ty2); tx1 = tx2; ty1 = ty2; } // Prevent rounding gap writer.LineTo(x3, y3); //DrawLine(context, w, h, tx1, ty1, x3, y3, color); } }