Creating a C #

0

Good afternoon friends, I'm creating a program in C # that should plot the current values of the serial port (arduino) in a picture box. To draw the graph I am creating points (x, y) and linking them forming drawline lines. In this way the graphic is drawn, but the "pen" that runs through the picturebox. I'm trying to do a similar effect to a seismograph (as if the picturebox that moved, such as the video link >). I think it's basically moving several lines. I'm currently doing this:

int contDRAW = 0, a; //contadores
private PointF[] vetpoint = new PointF[6000];//vetor para incrementar o X para fazer o deslocamento
float[] aquisicaoplot = new float[6000]; //vetor onde armazeno cada valor enviado pela serial

//a cada vez que for chamada a função desenhar já tenho um novo y
private void Desenhar()
        {
            vetpoint[contDRAW].Y = aquisicaoplot[contDRAW];
            for (a = 0; a <= contDRAW; a++)
            {
                if (contDRAW != a)
                {
                    vetpoint[a].X ++;
                }
                else vetpoint[a].X = 0;

                if (contDRAW == 0 || a==0) timerDRAW.Enabled = true;
                else graph.DrawLine(new Pen(Color.LightGreen, 0.1f), vetpoint[a - 1].X, 24 * aquisicaoplot[a-1], vetpoint[a].X, 24 *aquisicaoplot[a]);     
            }
            contDRAW++;
        }

private void timerDRAW_Tick(object sender, EventArgs e)
{
    Refresh();
}

This code comes close to the intended result. The chart is currently shifting, but it is reset and redrawn every time it goes into "for". What can I do? Am I on the right track? If anyone knows or has any tips on how I can do this effect please answer.

EDIT1:

I updated the Draw () function to the following:

private void Desenhar()
{
    System.Drawing.Pen myPen = new System.Drawing.Pen(System.Drawing.Color.LimeGreen, 0.1f);
    vetpoint[contDRAW].Y = 24*aquisicaoplot[contDRAW];
    for (a = 0; a <= contDRAW; a++)
    {
        if (contDRAW != a) vetpoint[a].X++;
        else vetpoint[a].X = 0;
    }
    if (contDRAW == 0) timerDRAW.Enabled = true;
    else graph.DrawLines(myPen, vetpoint);
    //else graph.DrawLine(myPen, vetpoint[contDRAW - 1].X, 24 * aquisicaoplot[contDRAW-1], vetpoint[contDRAW].X, 24 * aquisicaoplot[contDRAW]);
    contDRAW++;
    myPen.Dispose();
}

I've made a little progress in relation to the effect I want to produce, since the graph moves without being redrawn from the beginning, however, it is now very flicker and very delay after drawing several points.     

asked by anonymous 28.11.2018 / 17:43

1 answer

0

I made a check, see if it helps. Set the MinValue and MaxValue and DataCount properties - Amount of data to be appended. Just create a timer and call the AddValue method every time.

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApp2
{

public class GraphControl : Control
{
    private int _minValue = -100;
    private int _maxValue = 100;
    private int _dataCount = 25;
    private List<int> _values = new List<int>();

    public int MinValue
    {
        get => _minValue;
        set
        {
            _minValue = value;
            Invalidate();
        }
    }
    public int MaxValue
    {
        get => _maxValue;
        set
        {
            _maxValue = value;
            Invalidate();
        }
    }
    public int DataCount
    {
        get => _dataCount;
        set
        {
            _dataCount = value;
            Invalidate();
        }
    }

    public GraphControl()
    {
        Size = new System.Drawing.Size(500, 300);
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
    }

    public void AddValue(int value)
    {
        _values.Add(value);
        Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.FillRectangle(Brushes.White, ClientRectangle);
        e.Graphics.DrawRectangle(Pens.Gray, 0, 0, Width - 1, Height - 1);
        e.Graphics.DrawLine(Pens.LightGray, 0F, (float)Height * 0.5F, (float)Width, (float)Height * 0.5F);

        var wid = (float)Width / (float)_dataCount;

        for (var i = 0; i < _dataCount; i++)
            e.Graphics.DrawLine(Pens.LightGray, wid * i, 0F, wid * i, Height);

        var lastPoint = new PointF(0F, (float)Height * 0.5F);
        var idInit = _values.Count - _dataCount;

        if (idInit < 0)
            idInit = 0;

        for (int i = idInit, a = 0; i < _values.Count; i++, a++)
        {
            var value = (float)(_values[i] - MinValue);
            var total = (float)(MaxValue - MinValue);
            var porcent = value / total;
            var hg = porcent * Height;
            var newPoint = new PointF((a + 1) * wid, Height - hg);

            using (var p = new Pen(Color.Maroon, 2))
                e.Graphics.DrawLine(p, lastPoint, newPoint);

            lastPoint = newPoint;
        }

        base.OnPaint(e);
    }
}
}

Add the control to your project, compile it and then add it to Windows Forms via the toolbox.

Example with random values:

        private void timer1_Tick(object sender, EventArgs e)
    {
        var rd = new Random();
        var num = (rd.Next() % 200) - 100;

        graphControl1.AddValue(num);
    }
    
30.11.2018 / 17:30