1

i have a curve that i draw on a picturebox in c# using the method graphics.drawcurve(pen, points, tension)

is there anyway that i can extract all points (x,y coordinates) been covered by the curve ? and save them into an array or list or any thing would be great, so i can use them in a different things.

My code:

void Curved()
{
    Graphics gg = pictureBox1.CreateGraphics();
    Pen pp = new Pen(Color.Green, 1);
    int i,j;
    Point[] pointss = new Point[counter];

    for (i = 0; i < counter; i++)
    {
        pointss[i].X = Convert.ToInt32(arrayx[i]);
        pointss[i].Y = Convert.ToInt32(arrayy[i]);
    }
    gg.DrawCurve(pp, pointss, 1.0F);
}

Many thanks in advance.

Hossein Golshani
  • 1,847
  • 5
  • 16
  • 27
  • you draw it - just save point you passing into the `drawcurve` in some `List` – Tigran Sep 20 '18 at 21:06
  • Not really. But of course the data you use for drawing can be stored and reused. All the points covered by the drawing are not easy to collect. An approximation can be pulled by adding the curves to a graphicspath and then Flattening the path. The result are points of approximating lines; all should be on the curve. – TaW Sep 20 '18 at 21:09
  • 1
    Moore neighbor algorithm perhaps? https://gist.github.com/cwellsx/e9a1d7092203073c40565455c9b5c79d – Severin Pappadeux Sep 20 '18 at 21:16
  • i figured out that the method is based on cubic spline interpolation and i've updated my question and added the code – Ala'a Hassan Sep 20 '18 at 21:32
  • if the curve is the graph of a function, you should always render it straight from that function so the result adapts to the target device resolution. `DrawCurve`, mathematically, makes a [cardinal spline](https://learn.microsoft.com/de-de/windows/desktop/gdiplus/-gdiplus-cardinal-splines-about). When you sample it pixel by pixel, you are limited to that dimension and resolution, and lose the smoothing and antialiasing done by the graphics subsystem. – Cee McSharpface Sep 20 '18 at 21:34
  • @dlatikay pixel by pixel is exactly what i really need – Ala'a Hassan Sep 20 '18 at 21:37

1 Answers1

4

If you really want a list of pixel co-ordinates, you can still let GDI+ do the heavy lifting:

using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace so_pointsfromcurve
{
    class Program
    {
        static void Main(string[] args)
        {
            /* some test data */
            var pointss = new Point[]
            {
                new Point(5,20),
                new Point(17,63),
                new Point(2,9)
            };
            /* instead of to the picture box, draw to a path */
            using (var path = new GraphicsPath())
            {
                path.AddCurve(pointss, 1.0F);
                /* use a unit matrix to get points per pixel */
                using (var mx = new Matrix(1, 0, 0, 1, 0, 0))
                {                    
                    path.Flatten(mx, 0.1f);
                }
                /* store points in a list */
                var list_of_points = new List<PointF>(path.PathPoints);
                /* show them */
                int i = 0;
                foreach(var point in list_of_points)
                {
                    Debug.WriteLine($"Point #{ ++i }: X={ point.X }, Y={point.Y}");
                }
            }

        }
    }
}

This approach draws the spline to a path, then uses the built-in capability of flattening that path to a sufficiently dense set of line segments (in a way most vector drawing programs do, too) and then extracts the path points from the line mesh into a list of PointFs.

The artefacts of GDI+ device rendering (smoothing, anti-aliasing) are lost in this process.

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
  • you made my day , it worked for me but i need to modify it a little bit . thanks a lot for your time of helping me and thanks to everyone commented. – Ala'a Hassan Sep 20 '18 at 22:52
  • fyi to future readers, this produces a variable number of points (you can't control the exact number) and it won't fall on discrete x values like 1, 2, ..., n when the unit matrix isn't 1. For interpolating curves at a point, also see https://stackoverflow.com/questions/53679551/interpolating-a-cardinal-curve-in-c-sharp – person27 Jan 02 '22 at 02:46