Axis text isn't printed and coordinates aren't plotted - c#

The following code will only display the standard graph, but will not print the axis text nor plot any of the coordinates.
public void JapaneseCandleStick()
{
//GraphPane myPane = base.GraphPane;
GraphPane myPane = new GraphPane();
myPane.Title.Text = "Japanese Candlestick Chart Demo";
myPane.XAxis.Title.Text = "Trading Date";
myPane.YAxis.Title.Text = "Share Price, $US";
StockPointList spl = new StockPointList();
Random rand = new Random();
// First day is jan 1st
XDate xDate = new XDate(2006, 1, 1);
double open = 50.0;
for (int i = 0; i < 50; i++)
{
double x = xDate.XLDate;
double close = open + rand.NextDouble() * 10.0 - 5.0;
double hi = Math.Max(open, close) + rand.NextDouble() * 5.0;
double low = Math.Min(open, close) - rand.NextDouble() * 5.0;
StockPt pt = new StockPt(x, hi, low, open, close, 100000);
spl.Add(pt);
open = close;
// Advance one day
xDate.AddDays(1.0);
// but skip the weekends
if (XDate.XLDateToDayOfWeek(xDate.XLDate) == 6)
xDate.AddDays(2.0);
}
JapaneseCandleStickItem myCurve = myPane.AddJapaneseCandleStick("trades", spl);
myCurve.Stick.IsAutoSize = true;
myCurve.Stick.Color = Color.Blue;
// Use DateAsOrdinal to skip weekend gaps
myPane.XAxis.Type = AxisType.DateAsOrdinal;
// pretty it up a little
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0f);
zedGraphControl1.AxisChange();
//base.ZedGraphControl.AxisChange();
}
What is wrong with the above and why cannot I see any text or see the plots? It all compiles without errors, hence the referencing and the ZedGraph implementation/referencing seems to be in order.

when you create an instance of Graphpane it must be referenced to zedGraphControl1, use the following line of code :
GraphPane myPane = zedGraphControl1.GraphPane;
& here's the output:

Related

Add percent symbol to label on y axis in StackedColumn100

How do I format the Y axis label so it includes % symbol when using StackedColumn100?
I am using System.Windows.Forms.DataVisualization.Charting.Series charts.
here is my method for defining the chart look and feel (so far)...
private Series SetSeriesStyleStackedColumnPercentage(string sessionname, string color)
{
Series series = new Series(sessionname);
series.ChartType = SeriesChartType.StackedColumn100;
series.Color = Color.FromArgb(byte.Parse(color.Split(',')[0]),
byte.Parse(color.Split(',')[1]),
byte.Parse(color.Split(',')[2]),
byte.Parse(color.Split(',')[3]));
series.BorderWidth = 1;
series.BorderColor = Color.FromArgb(255, 0, 0, 0);
series.IsVisibleInLegend = true;
series.IsValueShownAsLabel = false;
return series;
}
There is no magic needed, just escape the percent character:
chart1.ChartAreas[yourCharArea].AxisY.LabelStyle.Format = "###0\\%";
or
chart1.ChartAreas[yourCharArea].AxisY.LabelStyle.Format = "###0.0\\%";
or whatever numeric formatting you need..

C# Chart use CustomLabels with scrollbar

I don't understand something. If i don't use the customlabels, the chart will use the default label. And then if I move the scrollbar , the chart size won't adjust. The Chart view maintain the original size.
But if I use this code to change the label at row 0. (other rows don't have this problem)
chart1.ChartAreas[0].AxisY2.CustomLabels.Add((i) ,
(i+1), (ntemp * 10).ToString(), 0, LabelMarkStyle.SideMark);
And Move the scrollbar, the chart View will be a little different for size. The chart will flicker, and I don't want it.
Thanks in advance.
Here is example
Random rand = new Random();
chart1.Series.Clear();
var series = chart1.Series.Add("My Series");
series.ChartType = SeriesChartType.RangeBar;
series.Color = Color.Black;
series.YAxisType = AxisType.Secondary;
for (int i = 10; i > 2; i--)
series.Points.AddXY(i, (rand.Next(3600, 7200)), (rand.Next(30000, 80000)));
var chartArea = chart1.ChartAreas[series.ChartArea];
chartArea.BorderDashStyle = ChartDashStyle.Solid; //最外圍的框框
chartArea.BorderWidth = 10;
chartArea.AxisY.Enabled = AxisEnabled.False;
chartArea.AxisY2.Enabled = AxisEnabled.True;
chartArea.AxisY2.LabelStyle.IntervalType = DateTimeIntervalType.Number;
chartArea.AxisY2.Interval = 3600;
chartArea.AxisY2.Minimum = 0;
chartArea.AxisY2.Maximum = 86400;
chartArea.AxisY2.ScaleView.Zoom(0, 3600 * 4);
for (int i = 0; i <= 24 * 6; i++)
{
int ntemp = i % 6;
if (ntemp != 0)
{
/*Problem Here !!*/
//chart1.ChartAreas[0].AxisY2.CustomLabels.Add((i) * 600, (i + 1) * 600, (ntemp * 10).ToString(), 0, LabelMarkStyle.Box);
}
}
chartArea.CursorY.AutoScroll = true;
chartArea.AxisY2.ScaleView.Zoomable = true;
chartArea.AxisY2.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
chartArea.AxisY2.ScrollBar.IsPositionedInside = false;
}
Well, I was intrigued about how and if this can be achieved with OxyPlot, and I think it can ...
Here's the code I've used, and here's a screenshot:
var model = new PlotModel("IntervalBarSeries") { LegendPlacement = LegendPlacement.Outside };
var temp_serie = new IntervalBarSeries
{
Title = "IntervalBarSeries 1",
FillColor = OxyColors.Black
};
var categoryAxis = new CategoryAxis
{
Position = AxisPosition.Left,
IsZoomEnabled = false, // No zoom on this axis
IsPanEnabled = false, // Right mouse move won't affect this axis
MajorGridlineStyle = LineStyle.Solid
,StartPosition = 1, EndPosition = 0 // This will reverse the order
};
var valueAxis = new LinearAxis(AxisPosition.Top)
{
MinimumPadding = 0.1, MaximumPadding = 0.1,
IsZoomEnabled = true,
MajorGridlineStyle = LineStyle.Solid,
MajorStep = 3600,
AbsoluteMinimum = 0
};
for (int i = 10; i > 2; i--)
{
temp_serie.Items.Add(new IntervalBarItem {
Start = rand.Next(3600, 7200),
End = rand.Next(30000, 80000)
});
categoryAxis.Labels.Add("Activity "+i);
}
model.Series.Add(temp_serie);
model.Axes.Add(categoryAxis);
model.Axes.Add(valueAxis);
MyPlotModel = model;
Now, I'm using MVVM and just binding to the plot model from my View with:
<oxy:Plot Model="{Binding MyPlotModel}"/>
But you can figure out how to do the same with WinForms once (if?) you decide to use OxyPlot and import it.
I'm assuming you're doing some work that is related to times, but your code obviously doesn't say so ... you could play around with the top header, and maybe set how to show the numbers (ATM, with no zoom, they overlap each other a bit. zooming with scroller solves that, but that's just because i've set the tick size to 3600 ... )

Drawing an GraphObj to Zedgraph control

I have a zedgraph control where I got at the the basic line chart of sine and cosine wave (from tutorial)
I am trying to add a BoxObj to the curve by clicking on it (code below) and I see that the BoxObj is added to GraphObjList, but nothing is actually drawn. Can it be the location that I give the object?
//This works
void zedGraphControl1_Click(object sender, EventArgs e)
{
Point p = (e as MouseEventArgs).Location;
CurveItem nearestCurve;
int index;
this.zedGraphControl1.GraphPane.FindNearestPoint(new PointF(p.X, p.Y), out nearestCurve, out index);
//Check for null when no curve clicked
if (nearestCurve == null)
return;
BoxObj box = new BoxObj(nearestCurve[index].X, nearestCurve[index].Y, 1, 0.1, Color.Black,Color.Red);
box.IsVisible = true;
box.Location.CoordinateFrame = CoordType.AxisXYScale;
box.ZOrder = ZOrder.A_InFront;
zedGraphControl1.GraphPane.GraphObjList.Add(box);
zedGraphControl1.Invalidate();
}
Here is the whole graph creation
public void CreateGraph(zedGraph ZedGraphControl)
{
// Lets generate sine and cosine wave
double[] x = new double[100];
double[] y = new double[100];
double[] z = new double[100];
for (int i = 0; i < x.Length; i++)
{
x[i] = i;
y[i] = Math.Sin(0.3 * x[i]);
z[i] = Math.Cos(0.3 * x[i]);
}
// This is to remove all plots
zedGraph.GraphPane.CurveList.Clear();
// GraphPane object holds one or more Curve objects (or plots)
GraphPane myPane = zedGraph.GraphPane;
// PointPairList holds the data for plotting, X and Y arrays
PointPairList spl1 = new PointPairList(x, y);
PointPairList spl2 = new PointPairList(x, z);
// Add cruves to myPane object
LineItem myCurve1 = myPane.AddCurve("Sine Wave", spl1, Color.Blue, SymbolType.None);
LineItem myCurve2 = myPane.AddCurve("Cosine Wave", spl2, Color.Red, SymbolType.None);
myCurve1.Line.Width = 3.0F;
myCurve2.Line.Width = 3.0F;
myPane.Title.Text = "My First Plot";
// I add all three functions just to be sure it refeshes the plot.
zedGraph.AxisChange();
zedGraph.Invalidate();
zedGraph.Refresh();
}
Environment:
MS Visual Studio 2010 and .NET Framework 4.0 on Windows XP
You're right, the location is wrong. The click-Event gives you the display-coordinates, but the BoxObj Constructor needs either units of your axis-scales or fraction of the chart-rect, depending on the CoordType of your BoxObj.
So you have to decide, which CoordType is more handy to you, convert the event-location to this type and also assign the CoordType to your BoxObj, for instance:
box.Location.CoordinateFrame = CoordType.XScaleYChartFraction;
EDIT: For testing you could try the following, and the box should be in the middle of your chart:
BoxObj box = new BoxObj(0.5, 0.5, 40, 40, Color.Black,Color.Red);
box.Location.CoordinateFrame = CoordType.ChartFraction;

Random elements (coordinates)

I have to do something like this.
When I click on a node, it expands, and this is OK (I am using Powercharts to do it).
My big problem is creating random coordinates so that when I open the subnode, it doesn't overlap with another node/subnode.
In the Powercharts I have to pass the coordinates, so the big problem is in passing it.
I have to do the random coordinates in C#.
//-------------------------------------------------------
This is what i did so far:
This is what i do, is not overlaping, but i have a problem.
how can i start do the circles from a starting point?
for example, starts in the middle (300,300) and then do circles around it. Is possible?
private void button2_Click(object sender, EventArgs e)
{
g = pictureBox1.CreateGraphics();
g.Clear(pictureBox1.BackColor);
double angle;
Circle item0 = new Circle();
item0.x=200;
item0.y=150;
item0.r=50;
listaCirculos.Add(item0);
Random randomMember = new Random();
g.DrawEllipse(pen1, 200, 150, 50, 50);
while(listaCirculos.Count!=11)
{
int[] it = GenerateNewCircle(600);
Circle item = new Circle();
item.x = it[0];
item.y = it[1];
item.r = 50;
if (circleIsAllowed(listaCirculos, item))
{
listaCirculos.Add(item);
g.DrawEllipse(pen1, Convert.ToInt32(item.x), Convert.ToInt32(item.y), 50, 50);
}
}
}
bool circleIsAllowed(List<Circle> circles, Circle newCircle)
{
foreach(Circle it in circles)
{
//double sumR = it.x + newCircle.r;
//double dx = it.x - newCircle.x;
//double dy = it.y - newCircle.y;
//double squaredDist = dx * dx + dy * dy;
double aX = Math.Pow(it.x - newCircle.x, 2);
double aY = Math.Pow(it.y - newCircle.y, 2);
double Dif = Math.Abs(aX - aY);
double ra1 = it.r / 2;
double ra2 = it.r / 2;
double raDif = Math.Pow(ra1 + ra2, 2);
if ((raDif + 1) > Dif) return false;
//if (squaredDist < sumR*sumR) return false;
}
return true; // no existing circle overlaps
}
public int[] GenerateNewCircle(int maxSize)
{
int x, y;
Random randomMember = new Random();
x = randomMember.Next(0,maxSize);
if (x - 50 < 0)
y = randomMember.Next(x + 50, maxSize);
else if (x + 50 > 600)
y = randomMember.Next(0, x - 50);
else
// in this case, x splits the range 0..n into 2 subranges.
// get a random number and skip the "gap" if necessary
y = randomMember.Next(0, maxSize - 50);
if (y > x - 50)
{
y += 20;
}
int[] abc = new int[2];
abc[0] = x;
abc[1] = y;
return abc;
}
Size sizeShape = new Size("SomeWidth" , "SomeHeight");
List<Retangle> rects = new List<Retangle>();
Random r = new Random();
while(rects.count != "someCount")
{
Point rPoint = new Point(r.Next(500) , r.Next(500))
bool isNew = true;
foreach(Rectangle r in rects)
{
if(r.contains(rPoint))
isNew = false;
}
if(isNew)
rects.Add(GetRect(rPoint , sizeShape));
}
private Rectangle GetRect(Point p , Size s)
{
return new Rectangle(p,s);
}
After than you can use from rects ,
rects has random coordinates.
Here's the link to let you know how to create Random Numbers in C#.
You have to keep in mind that you will generate random numbers, but you also have to make sure the numbers generated will not make objects overlap.
Despite this being pretty poorly worded, I believe what you are looking for is the Random class. It is instantiated as such:
Random thisRandom = new Random();
Then from there, if you want to generate a random coordinate, you need to know the maximum possible X and Y coordinates. Knowing these will allow you to generate X and Y coordinates within the given canvas as such:
int maxX = 500; //This is the maximum X value on your canvas
int maxY = 500; //This is the maximum Y value on your canvas
int newX, newY;
newX = thisRandom.Next(maxX);
newY = thisRandom.Next(maxY);
While its not the absolute best in terms of "true" randomization this should give you what you need.

Draw date on X axis and time on Y axis using ZedGraph and C#

In ZedGraph, how do I draw a time (like 00:00, 02:00, 04:00, etc.) on the Y axis and date (like 12-Apr-11, 13-Apr-11, 14-Apr-11, etc.) on the X axis?
The bar settings has been set to BarType.Stack.
Sample code will be very helpful.
Here is a sample that I constructed. I was not sure what sort of data you would plot along the Y Axis using a time format except for something like an accrued amount of time (such as number of hours employees worked).
ZedGraph uses an XDate format for time along the axes, which are doubles converted from datetimes. However in a stacked bar, I am not sure if ZedGraph can aggregate the times properly (I couldn't get it to work). Thus, in my example I used a Linear type for the Y Axis and changed the format so that it displays as hours and minutes.
Note that the min and max of both axes' scales have been set. This is especially important along the X axis, as the auto setting gets it wrong. Some of the other settings I specify clean up the minor tic marks, etc.
Here's an example showing a stacked bar graph for number of hours worked by three employees during each day:
const int NumberOfBars = 5;
GraphPane myPane = zedGraphControl1.GraphPane;
myPane.Title.Text = "Employee Hours";
myPane.BarSettings.Type = BarType.Stack;
myPane.BarSettings.ClusterScaleWidth = 1D;
// X AXIS SETTINGS
myPane.XAxis.Title.Text = "Date";
myPane.XAxis.Type = AxisType.Date;
myPane.XAxis.Scale.Format = "dd-MMM-yy";
myPane.XAxis.Scale.MajorUnit = DateUnit.Day;
myPane.XAxis.Scale.MajorStep = 1;
myPane.XAxis.Scale.Min = new XDate(DateTime.Now.AddDays(-NumberOfBars));
myPane.XAxis.Scale.Max = new XDate(DateTime.Now);
myPane.XAxis.MajorTic.IsBetweenLabels = true;
myPane.XAxis.MinorTic.Size = 0;
myPane.XAxis.MajorTic.IsInside = false;
myPane.XAxis.MajorTic.IsOutside = true;
// Y AXIS SETTINGS
myPane.YAxis.Title.Text = "Hours Worked";
myPane.YAxis.Type = AxisType.Linear;
myPane.YAxis.Scale.Format = #"00:\0\0";
myPane.YAxis.Scale.Min = 0;
myPane.YAxis.Scale.Max = 24;
myPane.YAxis.Scale.MajorStep = 1;
myPane.YAxis.MinorTic.Size = 0;
// Construct some sample data
Random r = new Random();
List<double> DatesX = new List<double>();
double[] JohnHours = new double[NumberOfBars];
double[] JoanHours = new double[NumberOfBars];
double[] JaneHours = new double[NumberOfBars];
for (int i = 0; i < NumberOfBars; i++)
{
DatesX.Add(new XDate(DateTime.Today.AddDays(-i)));
JohnHours[i] = r.Next(1, 9);
JoanHours[i] = r.Next(1, 9);
JaneHours[i] = r.Next(1, 9);
}
myPane.AddBar("John", DatesX.ToArray(), JohnHours, Color.Red);
myPane.AddBar("Joan", DatesX.ToArray(), JoanHours, Color.Blue);
myPane.AddBar("Jane", DatesX.ToArray(), JaneHours, Color.Green);

Categories