Question

I want to draw polyline (a continuous line composed of one or more line segments) on PictureBox.

In this we can create multiple lines by specifying the endpoints of each segment as well as calculate distance of each segment that is distance of each line.

Sample

Was it helpful?

Solution

If you want to do this on a picturebox, the easiest thing is to inherit your own control from a PictureBox and provide the functionality to add endpoints when you mouse down over the picturebox.

You then store the position of the mouse click in a list, and override the OnPaint to draw your endpoints (ive chosen a 4x4 square) and a line between each endpoint. This is the basic code:

public class EndPointPictureBox : PictureBox
{
    private List<PointF> points = new List<PointF>();
    public EndPointPictureBox()
    {
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        points.Add(new PointF(e.X,e.Y));
        base.OnMouseDown(e);
        this.Invalidate();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);

        Graphics g = pe.Graphics;
        foreach(var point in points)
            g.DrawRectangle(Pens.Black,point.X-2.0f,point.Y-2.0f,4.0f,4.0f);
        if(points.Count>1)
            g.DrawLines(Pens.Black,points.ToArray());

    }
}

You can now add this to a Form just like a PictureBox, and choose your imagge to go inside it in the usual way.

If you try clicking a few times inside the picturebox you'll see it draws your endpoints just like your example image. Here's an example from my machine:

Example endpoints

Then your next requirement, get the distance between endpoints. This can be done by adding a class to represent an EndPoint with a reference to its next-door neighbour. Then its some simple Pythagorean mathematics to get the distance between the current point and the next:

public class EndPoint
{
    public EndPoint(int index, List<PointF> points)
    {
        this.Position = points[index];
        if (index < points.Count - 1)
            this.Next = points[index + 1];
    }
    public PointF Position { get; private set; }
    public PointF Next { get; private set; }

    public double GetDistanceToNext()
    {
        if(this.Next == PointF.Empty)
            return 0;

        var xDiff = this.Position.X - Next.X;
        var yDiff = this.Position.Y - Next.Y;

        return Math.Abs(Math.Sqrt((xDiff*xDiff) + (yDiff*yDiff)));
    }
}

And you can add a method to your new PictureBox to obtain this a list of these:

public List<EndPoint> GetEndPoints()
{
    var list = new List<EndPoint>();
    for(var i=0;i<points.Count;i++)
        list.Add(new EndPoint(i,points));
    return list;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top