I have searched some examples of ZedGraph, but I couldn't perform what I wanted. I am drawing real-time data each 20 ms, and I want to show the system time on the x-axis (using the ZedGraph class XAxis). However when I try to draw milliseconds on the x-axis I cannot see any data. Here is my code:
//X-Axis Settings
pane.XAxis.Scale.MinorStep = 1;
pane.XAxis.Scale.MajorStep = 5;
pane.XAxis.Type = AxisType.Date;
pane.XAxis.Scale.Format = "HH:mm:ss.fff";
pane.XAxis.Scale.Min = new XDate(DateTime.Now);
pane.XAxis.Scale.Max = new XDate(DateTime.Now.AddSeconds(10));
pane.XAxis.Scale.MinorUnit = DateUnit.Second;
pane.XAxis.Scale.MajorUnit = DateUnit.Second;
XDate time = new XDate(DateTime.Now.ToOADate());
for (int i = 1; i < 16; i++)
{
listAuido.Add(time, (double)Read_Data1[i]);
}
Scale xScale1 = zgcMasterPane.MasterPane.PaneList[0].XAxis.Scale;
if (time.XLDate > xScale1.Max)
{
xScale1.Max = (XDate)(DateTime.Now.AddSeconds(1));
xScale1.Min = (XDate)(DateTime.Now.AddSeconds(-20));
}
Edit: This code structure is solved my problem.
The following code is drawing all the data on the same x point!
for (int i = 1; i < 16; i++)
{
listAuido.Add((XDate)(DateTime.Now.Millisecond), (double)Read_Data1[i]);
}
Why do you set your XAxis to the date format if you don't want it to appear like that?
OK, try this:
//Declare the x coordinate (time) variable
double xValue = 0;
//Setting the axis
pane.XAxis.Scale.MinorStep = 1;
pane.XAxis.Scale.MajorStep = 5;
pane.XAxis.Scale.Max = 0;
pane.XAxis.Scale.Min = -10;
//drawing the data
private void draw(double dataValue)
{
LineItem curve1 = zedGraphControl1.GraphPane.CurveList[0] as LineItem;
IPointListEdit list1 = curve1.Points as IPointListEdit;
list1.Add(xValue*(20/1000), dataValue); //
//Scroll
Scale XScale = zedGraphControl1.GraphPane.XAxis.Scale as Scale;
XScale.Max = xValue*(20/1000);
XScale.Min = XScale.Max - 10;
xValue++;
zedGraphControl1.AxisChange();
zedGraphControl1.Invalidate();
}
//Now you call the function draw every 20 ms using a [Timer][1] for example
private void timer1_Tick(object sender, EventArgs e)
{
draw(data[xValue]);
}
By the way I am not using MasterPane here.
Related
I am getting via the serial port some values from an aquisition board. I want to display the values on Y-axis and also have the time on the x-Axis. The values come from the serial port in batches that are NOT of equal size. I therefore created a time-stamp of my own. It doesn't work as seen in the picture below. However, if I set it to x-coordinate to 0 in AddXY, i get my result but of course without the time on the x-axis. I want to have it in seconds. I use a timer set to get data every 500 ms.
private void Timer_Tick(object sender, EventArgs e)
{
string data;
data = _port.ReadExisting();
Axis ax = chart1.ChartAreas[0].AxisX;
ax.IntervalType = DateTimeIntervalType.Milliseconds;
ax.Interval = 500;
chart1.Series[0].XValueType = ChartValueType.DateTime;
ax.LabelStyle.Format = "ss";
var dataBlocks = data.Split('\n');
int counter = 0;
double delta = (double)dataBlocks.Length / (double)500;
foreach (var block in dataBlocks)
{
var numbers = block.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < numbers.Length; i++)
{
double n = double.NaN;
bool ok = double.TryParse(numbers[i], out n);
if (ok)
{
if (n > 100)
{
double temp = counter * delta;
// double temp = 0;
chart1.Series[i].Points.AddXY(temp, n);
counter++;
if (chart1.Series[0].Points.Count > 1000)
chart1.Series[0].Points.RemoveAt(0);
//chart1.ResetAutoValues();
}
}
}
}
}
timer = new Timer();
timer.Tick += Timer_Tick;
timer.Interval = 500;
chart1.ChartAreas[0].AxisY.Maximum = 1024;
chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false;
chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
chart1.Series[0].Name = "Semnal EKG";[enter image description here][1]
I need your help.
I have a problem with the graph I need to create a graph with the X axis which is not linear.
I have tried every option with the option Logritmic and I could not because I get the opposite result
I attach the following picture illustrates what I need
The picture is an example from the Internet, but it describes exactly what I need X axis
If someone could help me I would appreciate it very much
The second picture shows what I have:
The function of the graph is the same function but the result is different as you see
the parameaters is :
pstati = 105
psheari = 90
currentflow = 447
This is a Code
private void PlotChart()
{
chart.Series[0].Points.Clear();
int currentflow = 0, pstati = 0, psheari = 0;
double ans = 0, hr, hf;
currentflow = int.Parse(tbAnsFlow.Text);
psheari = int.Parse(tbPSheari.Text);
pstati = int.Parse(tbPStatic.Text);
for (int i = 0; i <= pstati; i++)
{
hr = (pstati - i);
hf = (pstati - psheari);
ans = hr / hf;
ans = (Math.Pow(ans, 0.54)) * currentflow;
chart.Series[0].Points.AddXY(ans, i);
if (i == int.Parse(tbPSheariToCalc.Text))
{
chart.Series[0].Points[i].MarkerStyle = MarkerStyle.Circle;
chart.Series[0].Points[i].MarkerSize = 8;
chart.Series[0].Points[i].MarkerColor = Color.Black;
chart.Series[0].Points[i].LabelAngle = 0;
chart.Series[0].Points[i].Label = Math.Round(ans).ToString();
chart.Series[0].Points[i].LabelBorderColor = Color.Black;
chart.Series[0].Points[i].LabelBackColor = Color.WhiteSmoke;
tbAnsFlowCalc.Text = Math.Round(ans).ToString();
}
}
}
Is there a way to animate a chart in a C# Form Application in Visual Studio 2013 to show the line being gradually drawn onto the screen once a button is pressed? Thanks in advance :)
Here is an example that should get you started. It first creates test data and then uses a Timer to display them..:
List<PointF> data = new List<PointF>();
Timer timer = new Timer();
private void button1_Click_1(object sender, EventArgs e)
{
data.Clear();
for (int i = 0; i < 400; i++)
{
float x = i / 50f * (float)( Math.Cos(i / 10f));
float y = i / 50f * (float)(Math.Sin(i / 10f));
data.Add(new PointF(x,y));
}
chart1.Series.Clear();
Series S1 = chart1.Series.Add("S1");
Series S2 = chart1.Series.Add("S2");
S2.MarkerSize = 2;
S2.MarkerStyle = MarkerStyle.Circle;
S2.Color = Color.Green;
S1.Color = Color.FromArgb(64, Color.Red);
S1.BorderWidth = 9;
S2.ChartType = SeriesChartType.Point;
S1.ChartType = SeriesChartType.Line;
chart1.ChartAreas[0].AxisX.Minimum = -10;
chart1.ChartAreas[0].AxisX.Maximum = 10;
chart1.ChartAreas[0].AxisY.Minimum = -10;
chart1.ChartAreas[0].AxisY.Maximum = 10;
chart1.ChartAreas[0].BackColor = Color.White;
timer.Interval = 15;
timer.Start();
}
Note that I am using a PointF structure to store the test data as it is a handy floating point structure..
This is the Timer.Tick event. Don't forget to hook it up! Here we draw all data until we are through; then we stop the Timer:
void timer_Tick(object sender, EventArgs e)
{
Series S1 = chart1.Series[0];
Series S2 = chart1.Series[1];
int pointsSoFar = S1.Points.Count;
if (pointsSoFar < data.Count)
{
S1.Points.AddXY(data[pointsSoFar].X, data[pointsSoFar].Y);
S2.Points.AddXY(data[pointsSoFar].X, data[pointsSoFar].Y);
}
else
{
timer.Stop();
chart1.ChartAreas[0].BackColor = Color.AntiqueWhite;
}
}
Note that I have chosen to draw the Lines in a semitransparent color. It is instructive to watch the results of the strong overlapping of the line segments!
And here..
..the resulting..
.. animation..:
I have a problem with charts in my application. I want to use charts to display histograms of pictures. I want to add a gradient rectangle under chart with colors from black to R/G/B/White, so I draw it as Background Image of each chart. When values on AxisY ar greater then 1k everything is fine, but when those values have less then 4 digits there is a problem screen. Anyone know how to prevent extension of AxisX?
Init charts:
for(int i = 0; i < 3; i++)
{
ca = new ChartArea();
ca.AxisX.Interval = 1D;
ca.AxisX.IntervalOffsetType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
ca.AxisX.LabelAutoFitStyle = System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.WordWrap;
ca.AxisX.MajorGrid.Enabled = false;
ca.AxisY.MajorGrid.LineColor = System.Drawing.Color.DarkGray;
ca.BackColor = System.Drawing.Color.Transparent;
ca.BackSecondaryColor = System.Drawing.Color.Transparent;
ca.BorderWidth = 0;
ca.Name = "ChartArea" + i.ToString();
ca.AxisY.LabelAutoFitStyle = LabelAutoFitStyles.DecreaseFont;
ca.AxisX.Minimum = 0;
ca.AxisX.Interval = 256;
ca.AxisY.IntervalAutoMode = IntervalAutoMode.VariableCount;
s = new Series();
s.BorderWidth = 0;
s.ChartArea = "ChartArea" + i.ToString();
s.IsVisibleInLegend = false;
s.Name = "Series" + i.ToString(); ;
s.Color = Colors[i];
s["PointWidth"] = "1";
HistCharts[i] = new Chart();
HistCharts[i].Anchor = AnchorStyles.Top | AnchorStyles.Right;
HistCharts[i].BackColor = Color.Transparent;
HistCharts[i].BackgroundImageLayout = ImageLayout.None;
HistCharts[i].BorderlineWidth = 0;
HistCharts[i].ChartAreas.Add(ca);
HistCharts[i].Location = new System.Drawing.Point(405, (i + 3) * Form.Height / 6 - 28);
HistCharts[i].Name = "Chart" + i.ToString();
HistCharts[i].Series.Add(s);
HistCharts[i].Size = new System.Drawing.Size(297, Form.Height / 6 - 27);
HistCharts[i].TabIndex = 6;
HistCharts[i].Text = "chart" + i.ToString();
HistCharts[i].Visible = false;
HistCharts[i].SendToBack();
}
SetChartImage();
for(int i = 0; i < 3; i++)
HistCharts[i].BackgroundImage = HistImages[i];
Set new series and paint:
if(Hists == null)
{
HistCharts[0].Visible = false;
HistCharts[1].Visible = false;
HistCharts[2].Visible = false;
UpdateStatTimer(Time);
return;
}
HistCharts[0].BackgroundImage = HistImages[Hists.Length > 1 ? 1 : 0];
if(Hists[0].SequenceEqual(Hists[1]) && Hists[0].SequenceEqual(Hists[2]))
{
HistCharts[0].Series[0].Color = Color.Black;
HistCharts[0].BackgroundImage = HistImages[0];
HistCharts[0].Visible = true;
HistCharts[1].Visible = false;
HistCharts[2].Visible = false;
}
else
{
HistCharts[0].Series[0].Color = Color.Red;
HistCharts[0].BackgroundImage = HistImages[1];
HistCharts[0].Visible = true;
HistCharts[1].Visible = true;
HistCharts[2].Visible = true;
}
int Max = 0;
for(int i = 0; i < 3; i++)
{
HistCharts[i].Series[0].Points.Clear();
HistCharts[i].ChartAreas[0].AxisY.Maximum = Double.NaN;
for(int j = 0; j < Hists[i].Length; j++)
HistCharts[i].Series[0].Points.AddXY(j + 0.5, Hists[i][j]);
HistCharts[i].Update();
if(HistCharts[i].ChartAreas[0].AxisY.Maximum > Max)
Max = (int) HistCharts[i].ChartAreas[0].AxisY.Maximum;
}
if(StatisticsItemCheck.Checked == false)
{
for(int i = 0; i < 3; i++)
HistCharts[i].ChartAreas[0].AxisY.Maximum = Max;
}
if all Hists are equal Green and Blue histograms are invisible and Red Histogram becomes GrayScale Histogram
This is not really about scaling..:
The reason your images don't always align with the Y-Axis is that the Y-Axis legend takes more or less room in various cases. This make the inner plot area move to the right and your carefully aligned image doesn't fit anymore.
When the Y-Axis moves to the right the whole plotarea shrinks, at least if the default vlaues of Auto are still valid for the various elements..
The simplest workaround is to set the position from Auto to a fixed value that suits all your data:
chart1.ChartAreas[0].InnerPlotPosition.X = someValue;
Note that all element position values are in percent of the whole chart! So maybe you will want to modify it upon resizing the chart..? As you have noticed, you also have to resize you images..
To find a good value you can use the debugger to see which are the current ones in both of your cases and pick the larger one and then some extra for safety..
In the same veign you may want to get better control over the format, i.e. the number of digits on your y-axis label values, maybe like this..:
chart1.ChartAreas[0].AxisY.LabelStyle.Format = "0.00"; // some formatstring
Update:
To make use of the system's AutoScaling during(after a resize, you can use this workaround:
First set the Auto on and copy the resulting Elementposition. Then use those values to create a new one under control:
int LeftEdge = yourValue;
chart1.ChartAreas[0].InnerPlotPosition.Auto = true;
ElementPosition EP = chart1.ChartAreas[0].InnerPlotPosition;
chart1.ChartAreas[0].InnerPlotPosition =
new ElementPosition(LeftEdge, EP.Y, EP.Height, 100 - LeftEdge);
I'm using Teechart for .net V3.
When trying to rotate the X-labels to 45° some of the labels are not displayed, but if the angle is set to 90° it is OK.
Please see the following images:
This is 45° rotation:
This is 90° rotation:
Is it possible to show all the labels with 45° angle?
I think you can use custom labels to achieve all labels appear when you use an angle of 45º. You can do something as next code:
private Steema.TeeChart.TChart tChart1;
public Form1()
{
InitializeComponent();
tChart1 = new Steema.TeeChart.TChart();
this.Controls.Add(tChart1);
tChart1.Left = 100;
tChart1.Top = 50;
tChart1.Width = 500;
tChart1.Height = 350;
tChart1.Dock = DockStyle.Fill;
InitialzieChart();
}
private void InitialzieChart()
{
Steema.TeeChart.Styles.Bar bar1 = new Steema.TeeChart.Styles.Bar(tChart1.Chart);
DateTime dt = DateTime.Today;
Random rnd = new Random();
bar1.XValues.DateTime = true;
//bar1.date
for (int i = 0; i < 20; i++)
{
bar1.Add(dt, rnd.Next(100));
dt = dt.AddDays(5);
}
tChart1.Axes.Bottom.Labels.Angle = 45;
tChart1.Panel.MarginLeft = 10;
tChart1.Legend.Alignment = Steema.TeeChart.LegendAlignments.Bottom;
AddCustomLabels();
}
private void AddCustomLabels()
{
tChart1.Axes.Bottom.Labels.Items.Clear();
for (int i = 0; i < tChart1[0].Count; i++)
{
tChart1.Axes.Bottom.Labels.Items.Add(tChart1[0].XValues[i], DateTime.FromOADate(tChart1[0].XValues[i]).ToLongDateString());
}
}
Could you tell us if previous code works in your end?
Thanks,