Olá, pessoal!
Estou tentando plotar um gráfico de representativo de um ECG (eletrocardiograma) em uma PictureBox (Windows Form, C#). Os dados da curva do ecg estão em um array e eu consigo plotar eles sem problemas em um chart conforme código a seguir:
namespace PlotagemGrafica
{
public partial class Form1 : Form
{
int x = 10;
Byte() curva_ecg =
{
0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5d, //0
0x5d,0x5e,0x5e,0x5f,0x60,0x60,0x61,0x61,
0x62,0x62,0x63,0x63,0x64,0x64,0x65,0x65,
0x66,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,
0x6a,0x6b,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,
0x6c,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6e, //40
0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6d,0x6d,
0x6d,0x6d,0x6c,0x6c,0x6c,0x6b,0x6b,0x6a,
0x6a,0x6a,0x69,0x69,0x68,0x68,0x67,0x67,
0x66,0x66,0x65,0x65,0x64,0x64,0x63,0x63,
0x62,0x61,0x61,0x60,0x5f,0x5f,0x5e,0x5e, //80
0x5d,0x5d,0x5c,0x5c,0x5b,0x5b,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //120
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x59,0x57,0x54,0x52,0x4f,0x4d,0x4a,
0x48,0x45,0x43,0x40,0x3e,0x3d,0x3d,0x3e,
0x3f,0x44,0x4a,0x4f,0x55,0x5b,0x60,0x66, //160
0x6b,0x71,0x76,0x7c,0x82,0x87,0x8d,0x92,
0x98,0x9d,0xa3,0xa8,0xae,0xb4,0xb9,0xbf,
0xc4,0xca,0xcf,0xd5,0xdb,0xe0,0xe6,0xe1,
0xdb,0xd6,0xd1,0xcc,0xc6,0xc1,0xbc,0xb7,
0xb1,0xac,0xa7,0xa2,0x9c,0x97,0x92,0x8c, //200
0x87,0x82,0x7d,0x77,0x72,0x6d,0x68,0x62,
0x5d,0x58,0x53,0x4d,0x48,0x43,0x3e,0x38,
0x33,0x30,0x2d,0x2d,0x2e,0x31,0x34,0x37,
0x3b,0x3e,0x41,0x44,0x47,0x4a,0x4e,0x51,
0x54,0x56,0x58,0x58,0x59,0x59,0x59,0x59, //240
0x59,0x59,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //280
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,
0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,
0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,
0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63, //320
0x64,0x64,0x64,0x64,0x65,0x65,0x65,0x66,
0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,
0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,
0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,
0x6e,0x6f,0x6f,0x6f,0x6f,0x70,0x70,0x70, //360
0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x72,
0x73,0x73,0x73,0x73,0x74,0x74,0x74,0x74,
0x75,0x75,0x75,0x75,0x76,0x76,0x76,0x76,
0x77,0x77,0x77,0x77,0x77,0x77,0x78,0x78,
0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78, //400
0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,
0x79,0x78,0x78,0x78,0x78,0x78,0x78,0x78,
0x78,0x77,0x77,0x77,0x77,0x77,0x76,0x76,
0x75,0x75,0x74,0x74,0x74,0x73,0x73,0x72,
0x72,0x71,0x71,0x70,0x70,0x6f,0x6f,0x6e, //440
0x6d,0x6d,0x6c,0x6b,0x6b,0x6a,0x6a,0x69,
0x68,0x68,0x67,0x66,0x66,0x65,0x64,0x64,
0x63,0x62,0x62,0x61,0x60,0x60,0x5f,0x5e,
0x5e,0x5d,0x5c,0x5b,0x5b,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //480
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //520
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //560
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
};
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
chtGrafico.Legends.Clear();
chtGrafico.Series(0).ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Spline;
}
int i = 0;
private void timer_Tick(object sender, EventArgs e)
{
if (i > curva_ecg.Length - 1)
i = 0;
if (chtGrafico.Series(0).Points.Count > 1000)
{
chtGrafico.Series(0).Points.Clear();
chtGrafico.Update();
}
i++;
chtGrafico.Series(0).Points.AddXY(x++, curva_ecg(i));
}
}
}
Porém, ao tentar plotar esta mesma curva do ECG em uma PictureBox, a imagem plotada parece um gráfico de onda quadrada:
namespace DrawGraphics
{
public partial class Form1 : Form
{
Byte() curva_ecg =
{
0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5d, //0
0x5d,0x5e,0x5e,0x5f,0x60,0x60,0x61,0x61,
0x62,0x62,0x63,0x63,0x64,0x64,0x65,0x65,
0x66,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,
0x6a,0x6b,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,
0x6c,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6e, //40
0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6d,0x6d,
0x6d,0x6d,0x6c,0x6c,0x6c,0x6b,0x6b,0x6a,
0x6a,0x6a,0x69,0x69,0x68,0x68,0x67,0x67,
0x66,0x66,0x65,0x65,0x64,0x64,0x63,0x63,
0x62,0x61,0x61,0x60,0x5f,0x5f,0x5e,0x5e, //80
0x5d,0x5d,0x5c,0x5c,0x5b,0x5b,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //120
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x59,0x57,0x54,0x52,0x4f,0x4d,0x4a,
0x48,0x45,0x43,0x40,0x3e,0x3d,0x3d,0x3e,
0x3f,0x44,0x4a,0x4f,0x55,0x5b,0x60,0x66, //160
0x6b,0x71,0x76,0x7c,0x82,0x87,0x8d,0x92,
0x98,0x9d,0xa3,0xa8,0xae,0xb4,0xb9,0xbf,
0xc4,0xca,0xcf,0xd5,0xdb,0xe0,0xe6,0xe1,
0xdb,0xd6,0xd1,0xcc,0xc6,0xc1,0xbc,0xb7,
0xb1,0xac,0xa7,0xa2,0x9c,0x97,0x92,0x8c, //200
0x87,0x82,0x7d,0x77,0x72,0x6d,0x68,0x62,
0x5d,0x58,0x53,0x4d,0x48,0x43,0x3e,0x38,
0x33,0x30,0x2d,0x2d,0x2e,0x31,0x34,0x37,
0x3b,0x3e,0x41,0x44,0x47,0x4a,0x4e,0x51,
0x54,0x56,0x58,0x58,0x59,0x59,0x59,0x59, //240
0x59,0x59,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //280
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,
0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,
0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,
0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63, //320
0x64,0x64,0x64,0x64,0x65,0x65,0x65,0x66,
0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,
0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,
0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,
0x6e,0x6f,0x6f,0x6f,0x6f,0x70,0x70,0x70, //360
0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x72,
0x73,0x73,0x73,0x73,0x74,0x74,0x74,0x74,
0x75,0x75,0x75,0x75,0x76,0x76,0x76,0x76,
0x77,0x77,0x77,0x77,0x77,0x77,0x78,0x78,
0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78, //400
0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,
0x79,0x78,0x78,0x78,0x78,0x78,0x78,0x78,
0x78,0x77,0x77,0x77,0x77,0x77,0x76,0x76,
0x75,0x75,0x74,0x74,0x74,0x73,0x73,0x72,
0x72,0x71,0x71,0x70,0x70,0x6f,0x6f,0x6e, //440
0x6d,0x6d,0x6c,0x6b,0x6b,0x6a,0x6a,0x69,
0x68,0x68,0x67,0x66,0x66,0x65,0x64,0x64,
0x63,0x62,0x62,0x61,0x60,0x60,0x5f,0x5e,
0x5e,0x5d,0x5c,0x5b,0x5b,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //480
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //520
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, //560
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
};
const int historyLength = 512;
float() history = new float(historyLength);
int nextWrite = 0;
Graphics bmg;
Bitmap bm;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Timer timer1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// set initial values
for (int i = 0; i < historyLength; i++)
{
history(i) = 0;
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (bm == null)
{
bm = new Bitmap(historyLength, 101);
bmg = Graphics.FromImage(bm);
bmg.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //COMENTAR
bmg.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.GammaCorrected; //COMENTAR
bmg.Clear(Color.White);
}
Render();
e.Graphics.DrawImage(bm, 0, 0);
}
void Render()
{
bmg.Clear(Color.White);
float y0 = 0;
int x0 = 0;
for (int i = 0; i < historyLength; i++)
{
float y = 50.0f + 50.0f * history((nextWrite + i) % historyLength);
int x = i;
if (i != 0)
{
// draw a line
bmg.DrawLine(Pens.Black, x0, y0, x, y);
}
y0 = y;
x0 = x;
}
}
int t = 0;
private void timer1_Tick(object sender, EventArgs e)
{
AddValue(curva_ecg(t) / 120);
t++;
this.pictureBox1.Invalidate();
}
void AddValue(int y)
{
history(nextWrite) = y;
nextWrite = (nextWrite + 1) % historyLength;
}
}
}
O curioso é que este código eu usei como base para plotar uma senóide a qual saiu perfeita:
Existe algum tratamento que deve ser feito em um array para que ele seja plotado em uma PictureBox com base no tempo do timer?