PDPSharp chart location and background - c#

How can I get x,y location of graph wher X and Y Axis starts (x,y location of point 0,0 in line chart)? This location is changable depending on text values on Y Axis probably.
Image is for illustrative purpose only.
How can I change the background color (currently is linear blue) of chart (I use PDFsharp NuGet package)?
Sample code:
ChartFrame chartFrame = new ChartFrame();
chartFrame.Location = new XPoint(xOffset, yLoc);
double chartHeight = Math.Min(250, (page.Height - yLoc - 10));
chartFrame.Size = new XSize((page.Width - (xOffset * 2)), chartHeight);
Chart chart = new Chart(ChartType.Line);
//chart.PlotArea.FillFormat.Color = XColor.FromArgb(255, 255, 255, 255); //plot background???
Series series = chart.SeriesCollection.AddSeries();
series.ChartType = ChartType.Line;
series.MarkerStyle = PdfSharp.Charting.MarkerStyle.None;
series.Name = "Horizontal"; //Series 1
series.MarkerBackgroundColor = XColor.FromArgb(255, 0, 0, 255); //blue
series.MarkerSize = 1;
series.Add(line1);
series = chart.SeriesCollection.AddSeries();
series.ChartType = ChartType.Line;
series.MarkerStyle = PdfSharp.Charting.MarkerStyle.None;
series.Name = "Vertical"; //Series 2
series.MarkerBackgroundColor = XColor.FromArgb(255, 0, 170, 0); //green
series.MarkerSize = 1;
series.Add(line2);
series = chart.SeriesCollection.AddSeries();
series.ChartType = ChartType.Line;
series.MarkerStyle = PdfSharp.Charting.MarkerStyle.None;
series.Name = "3D position"; //Series 3
series.MarkerBackgroundColor = XColor.FromArgb(255, 255, 0, 0); //red
series.MarkerSize = 1;
series.Add(line3);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.XAxis.Title.Caption = "No. Events"; //X-Axis
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
double yOffset = ((maxYscale - minYscale) / 6);
if (yOffset < 0.01f)
yOffset = 0.01f;
chart.YAxis.MinimumScale = 0;
chart.YAxis.MaximumScale = Math.Round(Math.Round((maxYscale + yOffset), 3), 2);
double jump = Math.Round(yOffset, 2);
if (jump < 0.01f)
jump = 0.01f;
chart.YAxis.MajorTick = jump;
chart.YAxis.TickLabels.Format = "#0.00";
//chart.YAxis.HasMinorGridlines = true;
chart.YAxis.Title.Caption = "[m]"; //Y-Axis
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Color = XColors.DarkGray;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.Legend.Docking = DockingType.Bottom;
chart.Legend.LineFormat.Visible = true;
XSeries xseries = chart.XValues.AddXSeries();
xseries.Add(eventLine);
chartFrame.Add(chart);
chartFrame.Draw(gfx);

Re:for X,Y location:
I made quick check for text length on YAxis and then according to that calculate new X,Y position.
Re: Background color:
These colours are hard-coded in the ChartFrame class (Draw method). So the nugget package for PDFSharp is not good you need to download the library source code.
Search for "XColor.FromArgb(0xFFD0DEEF)" and update the source code as needed.

Related

Multiple Y axis Labels/Title overlap each others

I am showing multiple Y axis for chart by using below code. When any axis label value is having more than 3 digits then that axis Label/Title is getting overlap with other axis Label (as shown in image).
int leftIndex = 0, rightIndex = 0;
int relativePosition = 0;
foreach (Steema.TeeChart.Axis axis in this.tChart.Axes.Custom)
{
axis.Visible = true;
axis.PositionUnits = Steema.TeeChart.PositionUnits.Pixels;
axis.RelativePosition = 0 - (axis.OtherSide ? rightIndex++ : leftIndex++) * 60;
relativePosition = relativePosition + (axis.AxisRect().Width + 60);
}
You should be able to get your chart to render correctly by slightly modifying the constant in your calculation, e.g.
TChart _tChart;
public Form1()
{
InitializeComponent();
_tChart = new TChart();
_tChart.Dock = DockStyle.Fill;
_tChart.Series.Add(typeof(Line)).FillSampleValues();
_tChart.Series.Add(typeof(Line)).FillSampleValues();
_tChart.Series.Add(typeof(Line)).FillSampleValues();
_tChart.Series[0].YValues.Value = _tChart.Series[2].YValues.Value.Select(x => x * 100).ToArray();
_tChart.Header.Text = Utils.Version;
_tChart[0].CustomVertAxis = _tChart.Axes.Custom.Add();
_tChart[0].CustomVertAxis.Title.Text = "Axis One Title";
_tChart[0].CustomVertAxis.Title.Angle = 90;
_tChart[1].CustomVertAxis = _tChart.Axes.Custom.Add();
_tChart[1].CustomVertAxis.Title.Text = "Axis Two Title";
_tChart[1].CustomVertAxis.Title.Angle = 90;
_tChart[2].CustomVertAxis = _tChart.Axes.Custom.Add();
_tChart[2].CustomVertAxis.Title.Text = "Axis Three Title";
_tChart[2].CustomVertAxis.Title.Angle = 90;
int leftIndex = 0, rightIndex = 0;
for (int i = 0; i < this._tChart.Axes.Custom.Count; i++)
{
var axis = this._tChart.Axes.Custom[i];
axis.Visible = true;
axis.PositionUnits = Steema.TeeChart.PositionUnits.Pixels;
axis.RelativePosition = 0 - (axis.OtherSide ? rightIndex++ : leftIndex++) * (i == 1 ? 80: 70);
}
_tChart.Panel.MarginLeft = 30;
this.Controls.Add(_tChart);
}
Which here gives me:

Can we create 3D graph in 4 quadrants in C#.NET winform?

I want to create a 3D Graph in 4 quadrants form in C#.NET. For instant, I could do as shown below. If you see the corner of the chart begins with (-150, -200). I wish to start with (0,0) and the extend into 4 quadrant form.
Kindly enlighten me how can I transform this 3D graph in 4 quadrant form ?
Below is the corresponding code:
void prepare3dChart(Chart chart, ChartArea ca)
{
ca.Area3DStyle.Enable3D = true;
Series s = new Series();
chart.Series.Add(s);
s.ChartType = SeriesChartType.Bubble;
s.MarkerStyle = MarkerStyle.Diamond;
s["PixelPointWidth"] = "100";
s["PixelPointGapDepth"] = "1";
chart.ApplyPaletteColors();
addTestData(chart);
}
void addTestData(Chart chart)
{
Random rnd = new Random(9);
double x = 0, y = 0, z = 0;
for (int i = 0; i < 100; i++)
{
AddXY3d(chart.Series[0], x, y, z);
x = Math.Sin(i / 11f) * 88 + rnd.Next(3);
y = Math.Cos(i / 10f) * 88 + rnd.Next(5);
z = (Math.Sqrt(i * 2f) * 88 + rnd.Next(6));
}
}
int AddXY3d(Series s, double xVal, double yVal, double zVal)
{
int p = s.Points.AddXY(xVal, yVal, zVal);
s.Points[p].Color = Color.Transparent;
return p;
}
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart;
if (chart.Series.Count < 1) return;
if (chart.Series[0].Points.Count < 1) return;
ChartArea ca = chart.ChartAreas[0];
List<List<PointF>> data = new List<List<PointF>>();
foreach (Series s in chart.Series)
data.Add(GetPointsFrom3D(ca, s, s.Points.ToList(), e.ChartGraphics));
renderLines(data, e.ChartGraphics.Graphics, chart, true);
renderPoints(data, e.ChartGraphics.Graphics, chart, 6);
}
List<PointF> GetPointsFrom3D(ChartArea ca, Series s,
List<DataPoint> dPoints, ChartGraphics cg)
{
var p3t = dPoints.Select(x => new Point3D((float)ca.AxisX.ValueToPosition(x.XValue),
(float)ca.AxisY.ValueToPosition(x.YValues[0]),
(float)ca.AxisY.ValueToPosition(x.YValues[1]))).ToArray();
ca.TransformPoints(p3t.ToArray());
return p3t.Select(x => cg.GetAbsolutePoint(new PointF(x.X, x.Y))).ToList();
}
void renderLines(List<List<PointF>> data, Graphics graphics, Chart chart, bool curves)
{
for (int i = 0; i < chart.Series.Count; i++)
{
if (data[i].Count > 1)
using (Pen pen = new Pen(Color.FromArgb(64, chart.Series[i].Color), 2.5f))
if (curves) graphics.DrawCurve(pen, data[i].ToArray());
else graphics.DrawLines(pen, data[i].ToArray());
}
}
void renderPoints(List<List<PointF>> data, Graphics graphics, Chart chart, float width)
{
for (int s = 0; s < chart.Series.Count; s++)
{
Series S = chart.Series[s];
for (int p = 0; p < S.Points.Count; p++)
using (SolidBrush brush = new SolidBrush(Color.FromArgb(64, S.Color)))
graphics.FillEllipse(brush, data[s][p].X - width / 2,
data[s][p].Y - width / 2, width, width);
}
}
I want my 3D graph to have 4 quadrants like this:
Thanks #TaW. I got the code right.
void prepare3dChart(Chart chart, ChartArea ca)
{
ca.Area3DStyle.Enable3D = true;
ca.BackColor = Color.Transparent;
ca.AxisX.Minimum = -300;
ca.AxisX.Maximum = 300;
ca.AxisY.Minimum = -300;
ca.AxisY.Maximum = 300;
ca.AxisX.Crossing = 0; // move both axes..
ca.AxisY.Crossing = 0; // to the middle
ca.AxisX.Interval = 50;
ca.AxisY.Interval = 50;
ca.AxisX.MajorGrid.LineColor = Color.LightGray;
ca.AxisY.MajorGrid.LineColor = Color.LightGray;
chart.Series.Clear();
Series s = new Series();
chart.Series.Add(s);
s.ChartType = SeriesChartType.Bubble;
s.MarkerStyle = MarkerStyle.Diamond;
s["PixelPointWidth"] = "100";
s["PixelPointGapDepth"] = "1";
chart.ApplyPaletteColors();
addTestData(chart);
}
You can style the chart easily to look like this by moving both axes to the middle; this is done by setting their Crossings:
The code used is this:
ChartArea ca = chart1.ChartAreas[0];
ca.BackColor = Color.Transparent;
ca.AxisX.Minimum = -300;
ca.AxisX.Maximum = 300;
ca.AxisY.Minimum = -300;
ca.AxisY.Maximum = 300;
ca.AxisX.Crossing = 0; // move both axes..
ca.AxisY.Crossing = 0; // to the middle
ca.AxisX.Interval = 100;
ca.AxisY.Interval = 100;
ca.AxisX.MajorGrid.LineColor = Color.LightGray;
ca.AxisY.MajorGrid.LineColor = Color.LightGray;
Note that the real problem with MSChart in 3d-mode always remains the z-axis because there really isn't one. (If anybody is interested in how one can simulate it by having a lot of series see here. My example uses 32 series..)
You could draw it yourself, using the built-in function for the 3d conversions (TransformPoints) but this is a lot of tedious work, especially when it comes to labelling..
The updated code :
void prepare3dChart(Chart chart, ChartArea ca)
{
ca.Area3DStyle.Enable3D = true;
ca.BackColor = Color.Transparent;
ca.AxisX.Minimum = -300;
ca.AxisX.Maximum = 300;
ca.AxisY.Minimum = -300;
ca.AxisY.Maximum = 300;
ca.AxisX.Crossing = 0; // move both axes..
ca.AxisY.Crossing = 0; // to the middle
ca.AxisX.Interval = 50;
ca.AxisY.Interval = 50;
ca.AxisX.MajorGrid.LineColor = Color.LightGray;
ca.AxisY.MajorGrid.LineColor = Color.LightGray;
chart.Series.Clear();
Series s = new Series();
chart.Series.Add(s);
s.ChartType = SeriesChartType.Bubble;
s.MarkerStyle = MarkerStyle.Diamond;
s["PixelPointWidth"] = "100";
s["PixelPointGapDepth"] = "1";
chart.ApplyPaletteColors();
addTestData(chart);
}

Chart set (0,0) in the middle of the chart

I am trying to move Main X and Y axes to the point of (0,0), like:
I tried to add 4 lines: (-10,0) to (10,0) and (0-10) to (0,10)
Series ttt = new Series("")
{
ChartType = SeriesChartType.Line,
Color = Color.Yellow,
BorderWidth = 5,
Font = new Font(Font.OriginalFontName, 20, FontStyle.Regular),
};
ttt.Points.AddXY(0,10);
//ttt.Points.AddXY(0, -10);
this.chart1.Series.Add(ttt);
Unfortunately, also the Main X and Y axis moved to -10,-10 like:
Setting Axis.Crossing does the job. But I'm not sure how to get double arrows on each axis, but the following code gives this effect
ttt.Points.AddXY(0, 10);
ttt.Points.AddXY(10, 0);
ttt.Points.AddXY(0, -10);
ttt.Points.AddXY(-10, 0);
ttt.Points.AddXY(0, 10);
this.chart1.Series.Add(ttt);
chart1.ChartAreas[0].AxisX.Crossing = 0; // <--- These two lines
chart1.ChartAreas[0].AxisY.Crossing = 0;
And you probably also want to set the axis min/max by
chart1.ChartAreas[0].AxisX.Maximum = 15;
chart1.ChartAreas[0].AxisX.Minimum = -15;
chart1.ChartAreas[0].AxisY.Maximum = 15;
chart1.ChartAreas[0].AxisY.Minimum = -15;

ASP.NET Line Chart X-Axis Intervals Off

I am using an MSChart (System.Web.UI.DataVisualization.Charting.Chart()) Line Chart in an ASP.NET web page. It works fine except that the X-Axis intervals are off by 1 and I cannot figure out how to make they align to the right numbers. Here it is:
Notice the X-Axis (MPH) numbers: -1, 9, 19, 29....
Those are supposed to be 0, 10, 20, 30. I have taken measure in the code that I thought should have made it the way I want, but nothing works. My chart is 100% built in the c#, nothing in the ASPX. Here it is:
private void BuildLineChart(string reportName, List < DataPoint > points, string xTitle, string yTitle) {
var chart = new Chart();
// Build a column series
Series series = new Series(reportName);
series.ChartType = SeriesChartType.Line;
chart.Series.Add(series);
// Define the chart area
Grid grid = new Grid();
grid.LineWidth = 0;
ChartArea chartArea = new ChartArea();
chartArea.AxisX.MajorGrid = grid;
chartArea.AxisX.Crossing = 0;
chartArea.AxisX.Interval = 10;
chartArea.AxisX.IsStartedFromZero = true;
if (xTitle != string.Empty) {
chartArea.AxisX.Title = xTitle;
chartArea.AxisX.TitleAlignment = StringAlignment.Center;
chartArea.AxisX.TextOrientation = TextOrientation.Horizontal;
chartArea.AxisX.TitleFont = new Font("Verdana", 12);
}
if (yTitle != string.Empty) {
chartArea.AxisY.Title = yTitle;
chartArea.AxisY.TitleAlignment = StringAlignment.Center;
chartArea.AxisY.TextOrientation = TextOrientation.Rotated270;
chartArea.AxisY.TitleFont = new Font("Verdana", 12);
}
ChartArea3DStyle areaStyle = new ChartArea3DStyle(chartArea);
areaStyle.Rotation = 0;
chart.ChartAreas.Add(chartArea);
Axis xAxis = new Axis(chartArea, AxisName.X);
Axis yAxis = new Axis(chartArea, AxisName.Y);
// Set chart width and height (Note: increasing the width and height of the chart doesn't seem to improve the fidelity in the generated pdf (downstream))
chart.Width = new System.Web.UI.WebControls.Unit(800, System.Web.UI.WebControls.UnitType.Pixel);
chart.Height = new System.Web.UI.WebControls.Unit(300, System.Web.UI.WebControls.UnitType.Pixel);
// Bind the data to the chart
foreach(DataPoint point in points) {
chart.Series[reportName].Points.Add(point);
}
chart.Series[reportName].BorderWidth = 2;
//chart.Series[reportName].IsValueShownAsLabel = true;
string filename = Server.MapPath("./ChartImages") + "/" + reportName + ".png";
chart.SaveImage(filename, ChartImageFormat.Png);
}
var points = new List<DataPoint>();
points.Add(new DataPoint(0, 0));
points.Add(new DataPoint(8, 25));
points.Add(new DataPoint(9, 15));
points.Add(new DataPoint(14, 25));
points.Add(new DataPoint(15, 15));
points.Add(new DataPoint(22, 26));
points.Add(new DataPoint(23, 16));
points.Add(new DataPoint(36, 26));
points.Add(new DataPoint(36, 17));
points.Add(new DataPoint(53, 26));
points.Add(new DataPoint(53, 19));
points.Add(new DataPoint(73, 26));
BuildLineChart("GearSplit", points, "MPH", "RPM X 100");
Notice especially the Interval = 10 and the IsStartedFromZero = true.
Set the axis minimum value:
chartArea.AxisX.Minimum = 0;

Silverlight graphics pixel side position?

I try to port simple game to silverlight (SameGame). The problem is that my old source code used pixel sizes to allight game marks to board. I draw simple grid using lines and game mark (using rectangle). How i can set rentacle position correctly?
Example 20 20 pixels to upper left corner).
private void DrawGrid()
{
LayoutRoot.Children.Clear();
Rectangle r = new Rectangle();
r.Width = 20;
r.Height = 20;
r.Fill = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
r.Stroke = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
r.SetValue(Canvas.LeftProperty, (double)0);
r.SetValue(Canvas.TopProperty, (double)0);
LayoutRoot.Children.Add(r);
Color GridColor = Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
for (int y = 0; y < 11; y++)
{
Line l = new Line();
l.X1 = 0;
l.Y1 = 30 * y - 1;
l.X2 = 20 * 30;
l.Y2 = 30 * y - 1;
l.Stroke = new SolidColorBrush(GridColor);
l.StrokeThickness = 1;
LayoutRoot.Children.Add(l);
}
for (int x = 0; x < 21; x++)
{
Line l = new Line();
l.X1 = 30 * x;
l.Y1 = 0;
l.X2 = 30 * x;
l.Y2 = 10 * 30;
l.Stroke = new SolidColorBrush(GridColor);
l.StrokeThickness = 1;
LayoutRoot.Children.Add(l);
}
}
You need to put a Canvas below the LayoutRoot Grid or change LayoutRoot to a Canvas.
Then add the recangle to the Canvas.Children.

Categories

Resources