I am trying to display daily production data on a line chart in pounds of product produced per hour. We have 2 departments that appear on this chart however, some days 1 of the 2 departments may not be scheduled for production. On these days in my chart, I don't want to show a zero value for pounds per hour because it shows as a sharp dip in productivity. I need the line chart to skip that day for the zero value.Can anyone shed some light on how I can accomplish this?My datasource is a datatable with decimal values for the points on the line.Thanks in advance for your help,Trevor BraunThe Stirling Creamery Ltd.
assuming the "not scheduled" data in your datasource is null or DBNull,
UltraChart1.LineChart.NullHandling = DontPlot;
I have the same issue as Trevor and would like to have the line continue from the point for which a value exists on to the next point for which a value exists as if the columns (for which a particular row has no value) weren't even being graphed for that item.
In other words, if I weigh myself on 3 of 7 days and I weigh Foo Bar 5 of 7 days then I don't want my weight to dip down to zero on those other 2 days if I try to plot coordinates for both Foo Bar and myself in the same chart for that week.
I tried the line above just to see what the effect would be but I get an error message when I try to compile (C#): The name 'DontPlot' does not exist in the class or namespace
Fairly new to Infragistics. Using UltraWinChart.v7.1 and VS2003 (Version 7.1.6030 .NET Framework 1.1) as I have to write to a system (Eclipsys SCM v. 4.5) that requires it.
Would sure appreciate some code samples.
Thanks.
allen
you need to set the position of the point ... at this point, the value doesn't count for much.
you can find the position of a data value by mapping it on one or both of the axes...
IAdvanceAxis xAxis = this.Grid["X"] as IAdvanceAxis;
IAdvanceAxis yAxis = this.Grid["Y"] as IAdvanceAxis;
int positionX = Convert.ToInt32(xAxis.Map(5));
int positionY = Convert.ToInt32(xAxis.Map(5));
pl.points[x].point = new Point(positionX, positionY);
Didn't end up using any of the code above as yet.
I've basically got the component displaying the lines as I'd expect in the real world...
Null columns at the end of the period don't graph zero values (see Green for example which has 4 days with no values at the end of the period).
Null columns at the beginning of the period don't graph zero values (see Red which has no value for the first date column).
Null columns within the range of dates are not plotted but the slope of the line is maintained in line with the progression toward the next valid value (see Blue for example).
My issue now is that I am not plotting the value for Purple (8.5) which has non-valued dates all around it but should still show as a valid point on the graph. How to do this?
I'd like to post the code for this as well but I'm not sure how to do that. I'll post as a file if I have to but I'd rather paste into the body of the post as I see the Infragistics people doing successfully. How to do that?
Thanks,
Allen
the only way to do this is to handle FillSceneGraph, search for the isolated point, create a Symbol primitive for that point, and add it to the SceneGraph. the line chart is ignoring this point since 2 points are required to create a line segment.
You didn't answer the question about how to post code nicely like you do. Is that not possible?
I understand how to plot a point. My problem is that I don't understand the inheritance for the component well enough to determine that I've got a single point to map (that I have one significant value amongst nulls for that particular item). If I knew how to access the value for each day (in my example) to determine that only one of the days has a value to plot, I could then proceed to instantiate and plot an ellipse at that location.
allenovereem said:You didn't answer the question about how to post code nicely like you do. Is that not possible?
whoops. i just paste directly from visual studio into firefox, which doesn't really come out nicely. i think it works a lot better if you use IE.
allenovereem said:If I knew how to access the value for each day...
if you're using the Series collection as a datasource, it is easy, you can just loop through the DataPoints in each series.
if you're using the DataSource property of the chart, it's better to just go back to your data structure to find the isolated point.
if you can't do that for some reason, you can use the IChartData interface in FillSceneGraph...
IChartData chartData = e.ChartCore.GetChartLayer().ChartData;
// use chartData.GetRowCount(), GetColumnCount(), and GetValue(row, column) to iterate through your data.
Thanks David. I finally got to attempt this yesterday. I'm new to C# and not very good at it. I ended up creating a few more arraylists to capture the row and column and data values for passing to the getFillColor method and it did work. Maybe I'll figure out how to use a jagged array to make it more efficient. Will post some code later. Wanted to thank you and say that it worked. Thanks again!
allenovereem said:Now if I could just synch the color of the ellipse with the color that is going to be displayed for that point in the legend...any ideas?
The legend icons should also be in your SceneGraph, and their Path properties should all include the string "Legend." they will also have their Row and Column properties set... so you should be able to change the color of the legend items as needed.
or, you could try finding the correct color for your ellipse using this.ChartColorModel.getFillColor(...).
I modified slightly for my implementation and this works great.
Now if I could just synch the color of the ellipse with the color that is going to be displayed for that point in the legend...any ideas?
Your idea for posting code appears to work well too. Here I'm using Firefox and I've copied the code from VS2003 into WordPad and then copied that to here. At least at this point the formatting appears intact!
Thanks!
added to the end of FillSceneGraph...
IAdvanceAxis xAxis = this.Grid["X"] as IAdvanceAxis; IAdvanceAxis yAxis = this.Grid["Y"] as IAdvanceAxis; int rowCount = this.ChartData.GetRowCount(); int colCount = this.ChartData.GetColumnCount(); ArrayList iPointsOut = new ArrayList(); for (int r = 0; r < rowCount; r++) { int indexOfNonNullPoint = -1; bool isolated = true; for (int c = 0; c < colCount; c++) { object objectValue = this.ChartData.GetObjectValue(r, c); if (objectValue != null && !(objectValue is System.DBNull)) { if (indexOfNonNullPoint != -1) { isolated = false; break; } indexOfNonNullPoint = c; } } if (isolated) { object objectValue = this.ChartData.GetObjectValue(r, indexOfNonNullPoint); double dataValue = System.Convert.ToDouble(objectValue); int xPosition = System.Convert.ToInt32(xAxis.Map(indexOfNonNullPoint)); int yPosition = System.Convert.ToInt32(yAxis.Map(dataValue)); iPointsOut.Add(new Point(xPosition, yPosition)); } } //Point[] isolatedPoints = this.GetIsolatedPoints(); foreach (Point isolatedPoint in iPointsOut) { // draw an ellipse Ellipse plotPoint = new Ellipse(isolatedPoint, 4); plotPoint.PE.Fill = Color.Black; plotPoint.Layer = this; // add the ellipse to the scene. scene.Add(plotPoint); }
Thanks. This looks like it has the potential to do it. Unfortunately I'm using VS2003 (writing to SCM4.5) so I'll have to figure out how to implement it differently than you have here before I bless it. Again thanks and I'll be back.
this "GetIsolatedPoints" method should get you what you need, so in FillSceneGraph you can just use code like this:
Point[] isolatedPoints = this.GetIsolatedPoints(); foreach (Point isolatedPoint in isolatedPoints) { // draw an ellipse Ellipse plotPoint = new Ellipse(isolatedPoint, 4); plotPoint.PE.Fill = Color.Purple; plotPoint.Layer = this; // add the ellipse to the scene. scene.Add(plotPoint); }
private Point[] GetIsolatedPoints() { IAdvanceAxis xAxis = this.Grid["X"] as IAdvanceAxis; IAdvanceAxis yAxis = this.Grid["Y"] as IAdvanceAxis; int rowCount = this.ChartData.GetRowCount(); int colCount = this.ChartData.GetColumnCount(); List<Point> result = new List<Point>(); for (int r = 0; r < rowCount; r++) { int indexOfNonNullPoint = -1; bool isolated = true; for (int c = 0; c < colCount; c++) { object objectValue = this.ChartData.GetObjectValue(r, c); if (objectValue != null && !(objectValue is DBNull)) { if (indexOfNonNullPoint != -1) { isolated = false; break; } indexOfNonNullPoint = c; } } if (isolated) { object objectValue = this.ChartData.GetObjectValue(r, indexOfNonNullPoint); double dataValue = Convert.ToDouble(objectValue); int xPosition = Convert.ToInt32(xAxis.Map(indexOfNonNullPoint)); int yPosition = Convert.ToInt32(yAxis.Map(dataValue)); result.Add(new Point(xPosition, yPosition)); } } return result.ToArray(); }