Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cure C# winforms chart of the wiggles?

I'm implementing some real-time charts in a C# WPF application, but am using WinForms charts as they are generally easy to work with and are surprisingly performant.

Anyway, I've got the charts working just fine except for one major issue which I can't for the life of me figure out:

Wiggly Chart

When I add data to the chart, it sometimes just resizes itself. Sometimes it does that a lot, giving itself the wiggles and making the chart super annoying to read and deal with.

My question is: how can I prevent this damned chart from constantly resizing itself?!

Some additional information:

The chart is included in my XAML as such:

<WindowsFormsHost Grid.Row="1" Grid.ColumnSpan="2" Margin="5">
  <winformchart:Chart Dock="Fill" x:Name="Session0Chart">
    <winformchart:Chart.ChartAreas>
      <winformchart:ChartArea/>
    </winformchart:Chart.ChartAreas>
  </winformchart:Chart>
</WindowsFormsHost>

Gets initialized via:

// initialize it!
chart.Palette = ChartColorPalette.Bright;

// setup the labels
Font monoSpaceFont = new Font("Consolas", 10);
chart.ChartAreas[0].AxisX.LabelStyle.Font = monoSpaceFont;
chart.ChartAreas[0].AxisY.LabelStyle.Font = monoSpaceFont;

// set the axis limits appropriately
chart.ChartAreas[0].AxisY.Maximum = 600;
chart.ChartAreas[0].AxisY.Minimum = -200;

// set up grid lines and axis styles
chart.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
chart.ChartAreas[0].AxisX.MinorGrid.LineDashStyle = ChartDashStyle.Dash;
chart.ChartAreas[0].AxisX.MinorGrid.LineColor = System.Drawing.Color.Gray;
chart.ChartAreas[0].AxisX.MinorGrid.Interval = 0.04;
chart.ChartAreas[0].AxisX.LabelStyle.Format = "F2";
chart.ChartAreas[0].AxisX.LabelAutoFitStyle = LabelAutoFitStyles.None;

chart.ChartAreas[0].AxisY.MajorGrid.Enabled = true;
chart.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Solid;
chart.ChartAreas[0].AxisY.MajorGrid.Interval = 200;
chart.ChartAreas[0].AxisY.LabelAutoFitStyle = LabelAutoFitStyles.None;
chart.ChartAreas[0].AxisY.LabelStyle.Format = "F0";

chart.Series.Clear();

Series s = new Series();
s.ChartType = SeriesChartType.FastLine;
chart.Series.Add(s);
chart.Refresh();

And data points get added via:

// if we get too many points, remove the head
if (session.Chart.Series[0].Points.Count >= Properties.Settings.Default.ECGDataPoints)
{
    session.Chart.Series[0].Points.RemoveAt(0);
}

// add the points
for (int i = data.samples.Length - 1; i >= 0; i--)
{
    session.Chart.Series[0].Points.AddXY(session.ecgT, data.samples[i]);
    session.ecgT += session.ECGPeriod / (double)data.samples.Length;
}

// only look at the last few seconds
session.Chart.ChartAreas[0].AxisX.Maximum = session.ecgT;
session.Chart.ChartAreas[0].AxisX.Minimum = session.ecgT - Properties.Settings.Default.ECGTimeWindow;

Any help you can offer would be GREATLY appreciated, this has been driving me crazy for way too long!

like image 315
Hamaluik Avatar asked Mar 01 '16 21:03

Hamaluik


3 Answers

You can set ChartArea Position and InnerPlotPosition to avoid those wiggles.

chrt.ChartAreas[0].Position.Auto = false;
chrt.ChartAreas[0].Position.Height = 70;
chrt.ChartAreas[0].Position.Y = 5;

chrt.ChartAreas[0].InnerPlotPosition.Auto = false;
chrt.ChartAreas[0].InnerPlotPosition.Height = 50;
chrt.ChartAreas[0].InnerPlotPosition.Y = 10;
like image 84
Sarvesh Mishra Avatar answered Oct 11 '22 09:10

Sarvesh Mishra


chart.ChartAreas[0].InnerPlotPosition.X = 50;
chart.ChartAreas[0].InnerPlotPosition.Y = 5;
chart.ChartAreas[0].InnerPlotPosition.Width = 80;
chart.ChartAreas[0].InnerPlotPosition.Height = 80;

Read this.

like image 43
Loerinc Avatar answered Oct 11 '22 09:10

Loerinc


You should make your X axis DateTime, not double. It's an ECG anyway.... The wiggle is caused by incrementing your X axis with values such as 0.10000000001234.

enter image description here

// No wiggle
        chartNoWiggle.Series[0].Points.AddXY(xdatetime, r.NextDouble());

        if (chartNoWiggle.Series[0].Points.Count > 10)
            chartNoWiggle.Series[0].Points.RemoveAt(0);

        chartNoWiggle.ChartAreas[0].AxisX.Minimum = chartNoWiggle.Series[0].Points[0].XValue;
        chartNoWiggle.ChartAreas[0].AxisX.Maximum = xdatetime.ToOADate();

        xdatetime = xdatetime.AddMinutes(1);

// Wiggle
        chartWiggle.Series[0].Points.AddXY(xdouble, r.NextDouble());

        if (chartWiggle.Series[0].Points.Count > 10)
            chartWiggle.Series[0].Points.RemoveAt(0);

        chartWiggle.ChartAreas[0].AxisX.Minimum = chartWiggle.Series[0].Points[0].XValue;
        chartWiggle.ChartAreas[0].AxisX.Maximum = xdouble;

        xdouble += 0.10000000001234;
like image 24
jsanalytics Avatar answered Oct 11 '22 09:10

jsanalytics