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
...and I haven't explored removing the dots for the "faked" data points, although it should be possible since if you hover your mouse over the fake ones, no value is displayed. This would indicate that there is some way of detecting these points and removing the dots.
to remove all the dots, you can set LineChart.MidPointAnchors = None. you can also utilize the Data.EmptyStyle properties to enable custom line styling for segments surrounding null values.
if the property settings are insufficient, more customization is possible using the FillSceneGraph event to actually modify the Polyline primitives inside the SceneGraph.
in 7.1 i think the FillSceneGraph event is unavailable... in which case you'd have to implement ILayer (see the documentation topics on custom layers for more info).
Took me awhile to figure out that None above is actually a boolean value so I changed that to false in order to test that. That works well for setting that value for a line that has nulls within a range of values that includes a non-null value on either end of it.
I've managed to implement the ILayer interface and I'm working in the FillSceneGraph method. I'll post my code when I get it to work.
I'm stuck trying to set the value of the null point to some average.
In other words, if pl is my polyline and I have three points and pl.points[x].Value is for example 4...and pl.points[x+2].Value is 6 and pl.points[x+1] is null then I need to set the value of pl.points[x+1] to 5 but I'm not sure how to access that. It seems to be read-only at the level I find it.
I can modify the value of the x and y coordinates (assigning them the average of the x and y coordinates above and below) but this doesn't let me get close enough for the line to be accurate when trying to produce the average or point to plot for all permutations of values and number of points that are initially null values. I can set pl.points[x].point.X=whatever int and pl.points[x].point.Y=whatever int but...
what is the syntax to set the point directly to 5 as in pl.points[x=1].SetValue(5)?
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,
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(); }