I am using the chart component of .NET Framework 4.5 in C#.
When I fill that component with values that do not have the same gap to each other and set the ChartArea.Area3dStyle.Enable3d property to true, there is almost no impact on the chart until I equalize the gaps between the values in the series.
DataPoint dataPoint1 = new DataPoint(0D, 20D);
DataPoint dataPoint2 = new DataPoint(1D, 30D);
DataPoint dataPoint3 = new DataPoint(200D, 50D);
DataPoint dataPoint4 = new DataPoint(300D, 20D);
DataPoint dataPoint5 = new DataPoint(400D, 0D);
DataPoint dataPoint6 = new DataPoint(500D, 30D);
DataPoint dataPoint7 = new DataPoint(600D, 10D);
DataPoint dataPoint8 = new DataPoint(700D, 10D);
series1.Points.Add(dataPoint1);
series1.Points.Add(dataPoint2);
series1.Points.Add(dataPoint3);
series1.Points.Add(dataPoint4);
series1.Points.Add(dataPoint5);
series1.Points.Add(dataPoint6);
series1.Points.Add(dataPoint7);
series1.Points.Add(dataPoint8);
chartArea1.Area3DStyle.Enable3D = true;
You can set various parameters here. The one that directly makes up for the automtic downscaling with your large x-values is PointDepth
chartArea1.Area3DStyle.Enable3D = true;
chartArea1.Area3DStyle.PointDepth = 999; // pick a value you like
The best way to explore the many wonders of the Chart control is to play with it in the designer. When you have found a good setting you can go to the yourForm.Designer.cs file and look at the generated code; while you are not advised to fool around with it is a valuable resource for many obscure settings..
Unfortunately the maximum PointDepth is 1000 and with x-values larger than 300-500 the 3D-effect is still rather weak. Maybe you can downscale your values?
Related
I'm familiar with C# and Winform, but new to Chart control. I'm using VS2013 built in System.Windows.Forms.DataVisualization.Charting.Chart to display bar for two points. Here's simply the code:
private void Form1_Load(object sender, EventArgs e)
{
Chart c = new Chart();
c.Dock = DockStyle.Fill;
ChartArea a = new ChartArea();
a.AxisX.Minimum = 0;
a.AxisX.Maximum = 4;
a.AxisY.Minimum = 0;
a.AxisY.Maximum = 2;
c.ChartAreas.Add(a);
Series s = new Series();
//*******************
s.Points.AddXY(1, 1);
//s.Points.AddXY(2, 2);
s.Points.AddXY(3, 2);
//*******************
c.Series.Add(s);
this.Controls.Add(c);
}
Please note the commented part, the points (2,2) and (3,2) are only different data, and have nothing to do with display style(I guess?). So this behavior seems very strange and so far I haven't found any solution to keep displaying (3,2) like (2,2).
You need to add the below codes in order to achieve the desired output:
1] Fix the interval for the Axis so the axis label and Grid lines do not change.
a.AxisX.Interval = 1;
2] Fix the bar width for the series. You can use PixelPointWidth to specify the width in Pixels or PointWidth in Points.
Example using PixelPointWidth:
s["PixelPointWidth"] = "20";
Also, since you are using c.Dock = DockStyle.Fill; to fill the chart into whole form, fixed width will not be good if you scale the form.
You can use MinPixelPointWidth and MaxPixelPointWidth to give the range to the width.
s["MinPixelPointWidth"] = "20";
s["MaxPixelPointWidth"] = "80";
Check this link for details on different chart elements.
Technical Reference for detailed documentation on Chart controls. This may be long but important to understand the details.
On my Chart, I want to put an obvious red vertical bar which goes from a specific point on the plot down to the x-axis. Is there a way to do this? Based on the documentation, it doesn't seem like this option is available or perhaps I'm looking in the wrong area.
The most obvious way is to add a VerticalLineAnnotation.
Here is an example:
First I set up a few things:
int yourPointIndex = 635;
Series S1 = chart1.Series[0];
ChartArea CA1 = chart1.ChartAreas[0];
Now I create the Annotation and style it a little:
VerticalLineAnnotation LA = new VerticalLineAnnotation();
LA.LineColor = Color.Red;
LA.LineWidth = 9;
LA.IsInfinitive = false;
LA.AnchorDataPoint = S1.Points[yourPointIndex]; ;
Now I position it with the Point in question:
LA.X = S1.Points[yourPointIndex].XValue;
LA.Y = S1.Points[yourPointIndex].YValues[0];
// this makes the bar go down to the zero axis
LA.Height = LA.Y;
// this makes it go down all the way to the x-axis:
LA.Height = LA.Y - CA1.AxisY.Minimum;
// we should clip it to our chartarea:
LA.ClipToChartArea = CA1.Name;
Finally it is added to the Annotations collection of the Chart.
chart1.Annotations.Add(LA);
Note that Annotations can be adorned and made to be moveable..
Note: The code above was written for and tested with Winforms but the MS Chart control is rather similar in all its versions..
How is the approach to plot complex drawings with Direct2D (Sharpdx)?
Actually I am using a WindowsRenderTarget, connecting it with a Direct2D1.Factory and drawing to a RenderControl.
Factory2D = new SharpDX.Direct2D1.Factory(FactoryType.MultiThreaded);
FactoryWrite = new SharpDX.DirectWrite.Factory();
var properties = new HwndRenderTargetProperties();
properties.Hwnd = this.Handle;
properties.PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height);
properties.PresentOptions = PresentOptions.RetainContents;
RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
The drawing is done in the Paint Event of the form:
RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(Color4.Black);
drawProgress(); // Doing Paintings like DrawLine, Multiple PathGeometrys, DrawEllipse and DrawText
RenderTarget2d.EndDraw();
In the MouseMove/MouseWheel event the drawing will be recalculated (for scaling or calculation of the elements that will be displayed). This process need about 8-10ms.
The next step is actually
this.Refresh();
Here, I guess, is the problem, this progress needs up to 140ms.
So the scaling/moving of the plot has about 7fps.
Also the program occupies more and more memory when refreshing the Control
////Edit
Painting of lines:
private void drawLines(Pen pen, PointF[] drawElements)
{
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
int countDrawing = (drawElements.Length / 2) + drawElements.Length % 2;
for (int i = 0; i < countDrawing; i++)
{
drawLine(new Vector2(drawElements[i].X, drawElements[i].Y), new Vector2(drawElements[i + 1].X, drawElements[i + 1].Y), brushWhite);
}
}
Painting geometrys:
RenderTarget2D.DrawGeometry(graphicPathToPathGeometry(p), penToSolidColorBrush(pen));
private PathGeometry graphicPathToPathGeometry(GraphicsPath path)
{
geometry = new PathGeometry(Factory2D);
sink = geometry.Open();
if (path.PointCount > 0)
{
sink.BeginFigure(new Vector2(path.PathPoints[path.PointCount - 1].X, path.PathPoints[path.PointCount - 1].Y), FigureBegin.Hollow);
sink.AddLines(pointFToVector2(path.PathPoints));
sink.EndFigure(new FigureEnd());
sink.Close();
}
return geometry;
}
In mouse move the drawing will be recalculated by just building differences between Cursor.Position.X/Y old and Cursor.Position.X/Y new. So the the lines will be recalculated really often :)
The main bottleneck is your graphicPathToPathGeometry() function. You are creating and "filling" a PathGeometry in a render loop. As I mentioned above, a core principle is that you have to create your resources at once and then just reuse them in your drawing routine(s).
About your memory leak... your code samples don't provide enough information, but most probably you are not freeing the resources that you are creating (ie PathGeometry, SolidColorBrush and the ones we don't see).
The simplest advise is - use your render loop only for rendering/drawing and reuse resources instead of recreating them.
Improving the performance of Direct2D apps
One part of the problem is:
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
Creating objects of any kind inside the renderloop creates a big memory lack in the application. Drawing existing values is the way to go.
I guess the performance issue will also be based on this problem.
So I'm using Windows Forms Chart to generate graphs containing several lines that can create some clutter on the graph and need something to differentiate them other than color. There are too many points to using dotted or dashed lines as there is no observable difference between that and a continuous line. So what I'm hoping to do is to get markers with various shapes to show up on the lines like in Excel, for instance. Right now I'm have it coded like this
myChart.Series["MySeries"].ChartType = SeriesChartType.FastLine;
myChart.Series["MySeries"].MarkerStyle = MarkerStyle.Diamond;
What this does is put a diamond in the legend over that line, but it doesn't put diamonds on the actual line that is in the chart itself. Changing the marker size doesn't make a difference, unfortunately, and neither does changing the marker color. Is there a way to get that to happen. Thanks for reading, and any help you have.
EDIT:
Heres the relevant code.
Its data is held in a class that is the value-peice of a dictionary.
The class contains a list of doubles.
public void Charter(Color colorOfLine)
{
double xValue;
double yValue;
myChart.Series.Add("MySeries");
myChart.Series["MySeries"].ChartType.FastLine;
myChart.Series["MySeries"].ChartArea = "ChartArea1";
myChart.Series["MySeries"].Color = colorOfLine;
myChart.Series["MySeries"].MarkerStyle = MarkerStyle.Diamond;
myChart.Series["MySeries"].MarkerColor = Color.Black;
myChart.Series["MySeries"].MarkerSize = 5;
myChart.Series["MySeries"].MarkerBoarderColor = Color.DeepPink;
foreach (KeyValuePair<int, MyClass> Pair in MyDictionary)
{
xValue = Pair.Value.MyClassList[0];
yValue = Pair.Value.MyClassList[1];
myChart.Series["MySeries"].Points.AddXY(xValue, yValue);
}
}
I should add that I've played around with the MarkerStep, and MarkerBoarderWidth as well, all to no benefit. The issue seems to be that the marker simply isn't appearing on the actual lines in the chart itself. Also I'm using Visual Studio 2010 Express for what its worth. Thanks again for reading.
Use Line. Don't use FastLine. FastLine won't generate markers for you.
myChart.Series["MySeries"].ChartType = SeriesChartType.Line
Set the MarkerSize to something bigger:
myChart.Series["MySeries"].MarkerSize = 4;
ETA:
You may also need to set the color of the marker:
myChart.Series["MySeries"].MarkerColor = Color.Blue;
myChart.Series["MySeries"].Color = Color.Blue;
I've made a dynamic 3d piechart using devexpress. I'm really impressed with how good the control feature is. I've hit a little bit of a downer though.
I would like my pie chart points to have different colors that I set in code (this will later be changed by the user using some form of pallet or combo box, not sure yet). Unfortunatly I can't seem to get a color method for the points of my data series.
Here's the code excluding the mass of commented out attempts:
Series series1 = new Series("Series1", ViewType.Pie3D);
chartControl2.Series.Add(series1);
series1.DataSource = chartTable;
series1.ArgumentScaleType = ScaleType.Qualitative;
series1.ArgumentDataMember = "names";
series1.ValueScaleType = ScaleType.Numerical;
series1.ValueDataMembers.AddRange(new string[] { "Value" });
//series1.Label.PointOptions.PointView = PointView.ArgumentAndValues;
series1.LegendPointOptions.PointView = PointView.ArgumentAndValues;
series1.LegendPointOptions.ValueNumericOptions.Format = NumericFormat.Percent;
series1.LegendPointOptions.ValueNumericOptions.Precision = 0;
// Adjust the value numeric options of the series.
series1.Label.PointOptions.ValueNumericOptions.Format = NumericFormat.Percent;
series1.Label.PointOptions.ValueNumericOptions.Precision = 0;
// Adjust the view-type-specific options of the series.
((Pie3DSeriesView)series1.View).Depth = 20;
((Pie3DSeriesView)series1.View).ExplodedPoints.Add(series1.Points[0]);
((Pie3DSeriesView)series1.View).ExplodedPoints.Add(series1.Points[1]);
((Pie3DSeriesView)series1.View).ExplodedPoints.Add(series1.Points[2]);
((Pie3DSeriesView)series1.View).ExplodedPoints.Add(series1.Points[3]);
((Pie3DSeriesView)series1.View).ExplodedDistancePercentage = 20;
chartControl2.Legend.Visible = true;
So I need something like chartcontrol2.series1.point[0].color = color.blue; something like this.
Drawing in charts when drawing the series points of charts. To do this you should handle the ChartControl.CustomDrawSeriesPoint event, and then you can change some of the drawing parameters using its event args.
check these events to do your functinality..
How to: Custom Paint Series Points
ChartControl.CustomDrawSeries Event
You need to define a chart Palette or use an existing one defined by DevExpress. See this
http://documentation.devexpress.com/#XtraCharts/CustomDocument7434