Beispiel #1
0
        //=======================================================================
        //TODO: implement arc to ***

        /*
         * public void arc_to(double rx, double ry,
         *                     double angle,
         *                     bool large_arc_flag,
         *                     bool sweep_flag,
         *                     double x, double y)
         * {
         * if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command()))
         * {
         *  double epsilon = 1e-30;
         *  double x0 = 0.0;
         *  double y0 = 0.0;
         *  m_vertices.last_vertex(&x0, &y0);
         *
         *  rx = fabs(rx);
         *  ry = fabs(ry);
         *
         *  // Ensure radii are valid
         *  //-------------------------
         *  if(rx < epsilon || ry < epsilon)
         *  {
         *      line_to(x, y);
         *      return;
         *  }
         *
         *  if(calc_distance(x0, y0, x, y) < epsilon)
         *  {
         *      // If the endpoints (x, y) and (x0, y0) are identical, then this
         *      // is equivalent to omitting the elliptical arc segment entirely.
         *      return;
         *  }
         *  bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y);
         *  if(a.radii_ok())
         *  {
         *      join_path(a);
         *  }
         *  else
         *  {
         *      line_to(x, y);
         *  }
         * }
         * else
         * {
         *  move_to(x, y);
         * }
         * }
         * public void arc_rel(double rx, double ry,
         *                      double angle,
         *                      bool large_arc_flag,
         *                      bool sweep_flag,
         *                      double dx, double dy)
         * {
         * rel_to_abs(&dx, &dy);
         * arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy);
         * }
         */
        //=======================================================================


        /// <summary>
        /// approximate arc with curve4, cubic curve
        /// </summary>
        /// <param name="r1"></param>
        /// <param name="r2"></param>
        /// <param name="xAxisRotation"></param>
        /// <param name="largeArcFlag"></param>
        /// <param name="sweepFlags"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="isRelative"></param>
        public static void SvgArcToCurve4(this PathWriter _writer, float r1, float r2, float xAxisRotation, int largeArcFlag, int sweepFlags, float x, float y, bool isRelative)
        {
            using (VectorToolBox.Borrow(out SvgArcSegment svgArc))
            {
                if (isRelative)
                {
                    svgArc.Set(
                        (float)_writer.CurrentX, (float)_writer.CurrentY,
                        r1, r2,
                        xAxisRotation,
                        (SvgArcSize)largeArcFlag,
                        (SvgArcSweep)sweepFlags,
                        (float)(_writer.CurrentX + x), (float)(_writer.CurrentY + y));
                    //
                    svgArc.AddToPath(_writer);
                }
                else
                {
                    //approximate with bezier curve
                    svgArc.Set(
                        (float)_writer.CurrentX, (float)_writer.CurrentY,
                        r1, r2,
                        xAxisRotation,
                        (SvgArcSize)largeArcFlag,
                        (SvgArcSweep)sweepFlags,
                        x, y);
                    //
                    svgArc.AddToPath(_writer);
                }
            }
        }
Beispiel #2
0
        public static void CatmullRomToCurve4Rel(this PathWriter _writer, double dx0, double dy0, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
        {
            //https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
            //relative point
            double curX = _writer.CurrentX;
            double curY = _writer.CurrentY;

            CatmullRomSegmentToCurve4(_writer, curX + dx0, curY + dy0, curX + dx1, curY + dy1, curX + dx2, curY + dy2, curX + dx3, curY + dy3);
        }
Beispiel #3
0
 static TempContext <PixelFarm.CpuBlit.PathWriter> Borrow(out PixelFarm.CpuBlit.PathWriter pathWriter)
 {
     if (!Temp <PixelFarm.CpuBlit.PathWriter> .IsInit())
     {
         Temp <PixelFarm.CpuBlit.PathWriter> .SetNewHandler(
             () => new PixelFarm.CpuBlit.PathWriter(),
             w => w.UnbindVxs());
     }
     return(Temp <PixelFarm.CpuBlit.PathWriter> .Borrow(out pathWriter));
 }
Beispiel #4
0
        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);
        }
 public static void UnsafeDirectGetData(
     PathWriter pathStore,
     out int m_allocated_vertices,
     out int m_num_vertices,
     out double[] m_coord_xy,
     out byte[] m_CommandAndFlags)
 {
     VertexStore.UnsafeDirectGetData(
         pathStore.Vxs,
         out m_allocated_vertices,
         out m_num_vertices,
         out m_coord_xy,
         out m_CommandAndFlags);
 }
Beispiel #6
0
        /// <summary>
        /// Draws a Cardinal spline (cubic) defined by a point collection.
        /// The cardinal spline passes through each point in the collection.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="points">The points for the curve in x and y pairs, therefore the array is interpreted as (x1, y1, x2, y2, x3, y3, x4, y4, x1, x2 ..., xn, yn).</param>
        /// <param name="tension">The tension of the curve defines the shape. Usually between 0 and 1. 0 would be a straight line.</param>
        /// <param name="color">The color for the spline.</param>
        public static void DrawCurve(this PathWriter writer, float[] points, float tension)
        {
            // First segment
            SplineCurveSegment(writer, points[0], points[1], points[0], points[1], points[2], points[3], points[4], points[5], tension);
            // Middle segments
            int i = 2;

            for (; i < points.Length - 4; i += 2)
            {
                SplineCurveSegment(writer, points[i - 2], points[i - 1], points[i], points[i + 1], points[i + 2], points[i + 3], points[i + 4], points[i + 5], tension);
            }

            // Last segment
            SplineCurveSegment(writer, points[i - 2], points[i - 1], points[i], points[i + 1], points[i + 2], points[i + 3], points[i + 2], points[i + 3], tension);
        }
Beispiel #7
0
        public static void Hermite(this PathWriter pw, double[] xyCoords)
        {
            Curve4Points curve4_points = pw._c4_points;

            pw.MoveTo(xyCoords[0], xyCoords[1]);
            for (int i = 0; i < xyCoords.Length - (4 * 2);)
            {
                Curves.HermiteToBezier(
                    xyCoords[i], xyCoords[i + 1],
                    xyCoords[i + 2], xyCoords[i + 3],
                    xyCoords[i + 4], xyCoords[i + 5],
                    xyCoords[i + 6], xyCoords[i + 7],
                    curve4_points
                    );
                pw.Curve4(curve4_points.x1, curve4_points.y1,
                          curve4_points.x2, curve4_points.y2,
                          curve4_points.x3, curve4_points.y3
                          );
                i += 2;
            }
        }
Beispiel #8
0
        public static void CatmulRom(this PathWriter pw, double[] xyCoords)
        {
            Curve4Points curve4_points = pw._c4_points;

            pw.MoveTo(xyCoords[2], xyCoords[3]);//***
            for (int i = 0; i < xyCoords.Length - (4 * 2);)
            {
                Curves.CatromToBezier(
                    xyCoords[i], xyCoords[i + 1],
                    xyCoords[i + 2], xyCoords[i + 3],
                    xyCoords[i + 4], xyCoords[i + 5],
                    xyCoords[i + 6], xyCoords[i + 7],
                    pw._c4_points
                    );

                pw.Curve4(curve4_points.x1, curve4_points.y1,
                          curve4_points.x2, curve4_points.y2,
                          curve4_points.x3, curve4_points.y3
                          );
                i += 2;
            }
        }
Beispiel #9
0
 public static TempContext <PathWriter> BorrowPathWriter(VertexStore vxs, out PathWriter pathWriter) => VectorToolBox.Borrow(vxs, out pathWriter);
Beispiel #10
0
        public static TempContext <PixelFarm.CpuBlit.PathWriter> Borrow(VertexStore vxs, out PixelFarm.CpuBlit.PathWriter pathWriter)
        {
            var tmpPw = Borrow(out pathWriter);

            tmpPw._tool.BindVxs(vxs);
            return(tmpPw);
        }
Beispiel #11
0
        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);
            }
        }