Spline chart smooth corners - c#

I am using Chart control from .NET framework in my project. I have added chart control to the form and configured as shown below.
// Add a new series.
chart1.Series.Add("1");
var series = chart1.Series[0];
series.ChartType = SeriesChartType.Spline;
// Hide the legend.
series.IsVisibleInLegend = false;
// configure x axis.
var cArea = chart1.ChartAreas[0];
cArea.AxisX.IntervalType = DateTimeIntervalType.Number;
cArea.AxisX.LabelStyle.Format = "00";
cArea.AxisY.LabelStyle.Format = "0.000";
cArea.AxisY.LabelStyle.IsEndLabelVisible = true;
cArea.AxisX.Minimum = 0;
cArea.AxisX.Maximum = 100;
cArea.AxisX.Interval = 20;
cArea.AxisY.Minimum = 0;
cArea.AxisY.Maximum = 100;
cArea.AxisX.Interval = 20;
Data point values are as below:
chart1.Series[0].Points.AddXY(0, 5);
chart1.Series[0].Points.AddXY(5, 10);
chart1.Series[0].Points.AddXY(10, 30);
chart1.Series[0].Points.AddXY(20, 100);
chart1.Series[0].Points.AddXY(30, 100);
chart1.Series[0].Points.AddXY(40, 90);
chart1.Series[0].Points.AddXY(50, 80);
For the above data points, series is not smooth. Upper edge is getting cut. Refer attached image.
How to make it smooth so that whole line is visible ?

It's not visible because of the smoothing, adapt the scale (using cArea.AxisX.Maximum = 150; for example) or remove the smoothing to make the whole curve visible.

As with the DrawCurves GDI+ method you can control the tension of the splines, i.e. how close they are to the points and their connecting lines and how much smoothing they create. Too much 'smoothing' creates the fantasy tops you see and also crazy whirls from even small bumps in the data..
Setting the tension it is done via the LineTension Custom attribute.
Lower it from the default of 0.8 to something smaller. Test to see what you prefer.
Here is an example for a Series S :
S.SetCustomProperty("LineTension", "0.4");
Note that you still should make the y-axis Maximum a little larger or else you may need to bring the tension down to 0, which will look like a line type..
Here are a few variations:

Related

How to draw a stripline diagonally using MSChart?

Tweaking MS Charts. I have successfully draw a dynamic chart but need to draw a line (Yellow) across the chart. How will i draw (yellow) line. I have X and Y values.
Here is an example you can play with:
// we create a general LineAnnotation, ie not Vertical or Horizontal:
LineAnnotation lan = new LineAnnotation();
// we use Axis scaling, not chart scaling
lan.IsSizeAlwaysRelative = false;
lan.LineColor = Color.Yellow;
lan.LineWidth = 5;
// the coordinates of the starting point in axis measurement
lan.X = 3.5d;
lan.Y = 0d;
// the size:
lan.Width = -3.5d;
lan.Height = 5.5d;
// looks like we need an anchor point, no matter which..
lan.AnchorDataPoint = yourSeries.Points[0];
// now we can add the LineAnnotation;
chart1.Annotations.Add(lan);

C# Chart Control produces huge title for large heights

I'm developing several bar charts using chart controls in C#, one of which holds a series of ~2300 data points. In order to be able to properly display custom labels for each data point, I expanded the height of the chart to be 10000. However, it's now producing quite a large sized header and footer for the chart, as seen below:
When I set the chart to resume having a more normal height of 500, though, the title size goes back to being more reasonable. How can I manually adjust the title size?
Here's my code for the chart properties:
Chart chart = new Chart();
chart.Width = 1000;
chart.Height = 10000;
chart.BackColor = Color.FromArgb(211, 223, 240);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 1;
chart.Palette = ChartColorPalette.Bright;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
chart.Titles.Add("Hit Rate");
chart.IsSoftShadows = true;
chart.ChartAreas.Add("Left");
chart.ChartAreas["Left"].AxisX.Title = "Market Area";
chart.ChartAreas["Left"].AxisY.Title = "Hit Percentage";
UPDATE: I have added this to my code...
chart.ChartAreas["Left"].InnerPlotPosition.X = 5;
chart.ChartAreas["Left"].InnerPlotPosition.Y = 0f;
which has helped somewhat. In addition, I have found that it is not the size of the title in and of itself that is causing the problem. The height of the title is actually quite normal. Instead it is all the blank space allocated to the chart above the actual graphing area.
Let's try this :
chart.Titles[0].Position.Auto = false;
chart.Titles[0].Position.Width = 60; //change the size you want
auto = false means you manually calculate the location. I think by default the width of the title is 50% and 50% of the chart.
Ludo
Instead of setting the height and width of the chart manually why don't you leave it to set automatically according to the content and set the below:
chart.ChartAreas[0].AxisX.Interval = 1;
chart.ChartAreas[0].AxisY.Interval = 1;
(here i'm choosing chart area 0, change it according to your code)
As you add the above code do not set the height and width of the chart.
Let me know in case of issues

How to manually position ASP.Net Chart Legend?

Using the Chart controls built into ASP.Net, I'm trying to manually position the Title and the Legend so that they are directly next to each other horizontally just above the ChartArea. I've been able to manually position the Title using the following code:
chart.Titles["Title1"].Position.Auto = false;
chart.Titles["Title1"].Position.X = 10;
chart.Titles["Title1"].Position.Y = 5;
There's nothing to it, really. However, I'm attempting to position the Legend to the right of it with the following code, and the Legend doesn't even appear:
chart.Legends["Legend1"].Position.Auto = false;
chart.Legends["Legend1"].Position.X = 30;
chart.Legends["Legend1"].Position.Y = 5;
Any ideas what I'm doing wrong? This seems like it should be relatively simple. I've even tried various other coordinates, and I can't get the Legend to appear anywhere. It does appear if I use the built-in positioning such as below, but this positioning does not suit my purposes:
chart.Legends["Legend1"].Docking = Docking.Top;
chart.Legends["Legend1"].DockedToChartArea = "ChartArea1";
chart.Legends["Legend1"].IsDockedInsideChartArea = false;
chart.Legends["Legend1"].Alignment = StringAlignment.Far;
Try newing up an ElementPosition object, like this:
chart.Legends["Legend1"].Position.Auto = false;
chart.Legends["Legend1"].Position = new ElementPosition(30, 5, 100, 20);
Note: The constructor for ElementPosition takes 0 or 4 parameters (x, y, width, height).
I stumbled on this question for looking how to move legend at the bottom of a chart.
Answer for that is to use Docking property
Chart1.Legends["Legend1"].Docking = Docking.Bottom;
It may be helpful for someone in future, as this is the first link in google search.

Get chart area bounds in C#

Just to explain what I'm doing, I draw two selectors on a chart, and the part that will not be selected should appear under that blue rectangle. The part that will be selected will appear in the white area, between the two selectors. The figure below shows only the left selector.
Now, what I'm trying to do is to draw a rectangle inside a chart that always remain inside the plotting area, even when the windows is resized.
To get the top, left and bottom bounds, to draw the rectangle as shown in the figure below, I do the following:
(...)
int top = (int)(Chart.Height * 0.07);
int bottom = (int)(Chart.Height - 1.83 * top);
int left = (int)(0.083 * Chart.Width);
Brush b = new SolidBrush(Color.FromArgb(128, Color.Blue));
e.Graphics.FillRectangle(b, left, top, marker1.X - left, bottom - top);
(...)
But that's far from perfect, and it isn't drawn in the right place when the window is resized. I want the blue rectangle to always be bound on the top, left and bottom by the plotting area grid. Is that possible?
You probably want to use StripLine to achieve this.
Look into the Stripline Class Documentation.
Also I recommend downloading the Charting Samples which are a great help to understand the various features.
StripLine stripLine = new StripLine();
stripLine.Interval = 0; // Set Strip lines interval to 0 for non periodic stuff
stripLine.StripWidth = 10; // the width of the highlighted area
stripline.IntervalOffset = 2; // the starting X coord of the highlighted area
// pick you color etc ... before adding the stripline to the axis
chart.ChartAreas["Default"].AxisX.StripLines.Add( stripLine );
This assumes you are wanting something that is not what Cursor already does (see CursorX), such as letting the user mark up areas of the plot which provides some persistence. Combining the Cursor events with the striplines above would be a good way to do that.
So to highlight the start and end of the cursor you could do this
// this would most likely be done through the designer
chartArea1.AxisX.ScaleView.Zoomable = false;
chartArea1.CursorX.IsUserEnabled = true;
chartArea1.CursorX.IsUserSelectionEnabled = true;
this.chart1.SelectionRangeChanged += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CursorEventArgs>(this.chart1_SelectionRangeChanged);
...
private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
{
chart1.ChartAreas[0].AxisX.StripLines.Clear();
StripLine stripLine1 = new StripLine();
stripLine1.Interval = 0;
stripLine1.StripWidth = chart1.ChartAreas[0].CursorX.SelectionStart - chart1.ChartAreas[0].AxisX.Minimum;
stripLine1.IntervalOffset = chart1.ChartAreas[0].AxisX.Minimum;
// pick you color etc ... before adding the stripline to the axis
stripLine1.BackColor = Color.Blue;
chart1.ChartAreas[0].AxisX.StripLines.Add(stripLine1);
StripLine stripLine2 = new StripLine();
stripLine2.Interval = 0;
stripLine2.StripWidth = chart1.ChartAreas[0].AxisX.Maximum - chart1.ChartAreas[0].CursorX.SelectionEnd;
stripLine2.IntervalOffset = chart1.ChartAreas[0].CursorX.SelectionEnd;
// pick you color etc ... before adding the stripline to the axis
stripLine2.BackColor = Color.Blue;
chart1.ChartAreas[0].AxisX.StripLines.Add(stripLine2);
}
Somehow I suspect you may not have discovered the cursor yet, and doing so will make all this irrelevant. But anyway, the above code will do what you described.

C# Charting zoom problem with DataTime for X axis

using the MS Charting for .NET, I am trying to zoom into the chart which I have created.
This works fine on the Y axis (type = float) and on the X axis if type = int, but when I have DateTime values on the X axis, scrolling does not behave as it should on this axis.
Vertically, everything still behaves properly, but while I can zoom into the X axis, I cannot drag the sliding bar to move where I am zoomed into. However, I can click either side and it will jump.
Does anyone know how to fix this and make it behave like it does with float values?
Thanks!
Depending on your data, try setting the chart area's CursorX.IntervalType property to something other than Auto.
You may run into a similar issue when trying to use the small scroll arrows of the scroll bar once you are zoomed in. To fix that you can try to set the chart area's AxisX.ScaleView.SmallScrollSizeType property to the same thing as the CursorX.IntervalType.
For example, if you have a chart with data that is reported every 30 seconds you can use the following settings:
chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
chart1.ChartAreas[0].CursorX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Minutes;
chart1.ChartAreas[0].CursorX.Interval = 0.5D;
chart1.ChartAreas[0].AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Minutes;
chart1.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 0.5D;
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisX.LabelStyle.Format = "hh:mm:ss";
I had the same problem and these settings solve it for me:
_chart.ChartAreas[0].CursorX.IsUserEnabled = true;
_chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
_chart.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Minutes;
_chart.ChartAreas[0].CursorX.Interval = 1D;
_chart.ChartAreas[0].AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Minutes;
_chart.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 1D;
_chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
_chart.ChartAreas[0].AxisX.ScaleView.MinSizeType = DateTimeIntervalType.Minutes;
_chart.ChartAreas[0].AxisX.ScaleView.MinSize = 1D;
_chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Minutes;
_chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSize = 1D;
Especially the last two lines did the job.
add
chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSizeType = DateTimeIntervalType.Seconds;
My solution was:
chart1.ChartAreas[0].CursorX.IntervalType = DateTimeIntervalType.Milliseconds;

Categories

Resources