|
xZoneColor issue. |
Posted by Jaideep on May-17-2011 05:19 |
|
Hi,
I have the following scenario -
XY Line chart, the line color needs to change on every data point(and this comes from a DB value- say blue, green etc).
I have set up our code to use lay.xZoneColor(threshold,belowcolor,abovecolor) for each data point.
This set seems to work ok for a small dataset, but when there are a lot of datapoints, i am seeing weird behavior like missing line on certain datapoints, varying line widths etc. Is there an upper limit on the number of xZoneColor values that can be added on a particular chart layer? If yes, is there a work around for this scenario?
Please let me know.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on May-17-2011 18:07 |
|
Hi aideep,
You can use thousands xZoneColor values. However, if you are cascading x-zone colors (that is, the color used in an xZoneColor is another xZoneColor), you can only cascade up to 10 levels deep. Anyway, this limitation should not cause "varying line widths".
For your case, you mentioned you want to "change on every data point". Would you mind to clarify exactly which part of the chart would you like to have the color changed? In the XY Line chart, you have a symbol for each data points, and you have line segments which joins two data points. For example, if you have 100 data points, you will have 100 symbols, and 99 line segments.
In any case, we suggest you to separate the data into multiple data sets or layers. If you only have less than 1000 points, you can use one data set or layer per symbol or line segment. If you have tens of thousands or millions of points, you may want to separate them into data sets or layers, in which each data set or layer handles one color.
If you need further help, may be you can show me the chart you need, and the chart you are current getting so far.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on May-18-2011 00:17 |
|
Peter,
Thanks for the response.
So here is what i am currently doing. Say i have 100 rows of data(each representing one data point, so 100 data points and 99 line segments). I am trying to change the color of each of the line segments (based on the color value from that row of data).
Currently my approach was -
For each data value in NoOfRows
iLineSegmentColor = lay.xZoneColor(threshold,belowColor,aboveColor)
Next
-- threshold is an incremental value in this case going from 0 to 100
After the full loop above, i add this entire dataset to the layer.
ds = lay.addDataSet(yData,iLineSegmentcolor,label)
so for example the first few iterations of the above would produce
iLineSegmentColor = lay.xZoneColor(0,green,black)
iLineSegmentColor = lay.xZoneColor(1,green,black)
iLineSegmentColor = lay.xZoneColor(2,blue,black)
iLineSegmentColor = lay.xZoneColor(3,blue,black)
iLineSegmentColor = lay.xZoneColor(4,green,black)
(the result that i need to see really is the line segment starting off green at 0, then changing to blue and then whatever color is specified later on).
Is there something i need to change to make this work properly?
Please let me know.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on May-18-2011 00:51 |
|
Hi Jaideep,
May be I cannot understand your code, but I think your line will only contain 1 color.
After the 100 iterations, the execution is like:
iLineSegmentColor = lay.xZoneColor(0,green,black)
iLineSegmentColor = lay.xZoneColor(1,green,black)
.........
iLineSegmentColor = lay.xZoneColor(98,blue,black)
iLineSegmentColor = lay.xZoneColor(99,green,black)
So the iLineSegmentColor for the first 99 iteration is not used, and is overwritten in the next iteration. At the end, only the result of the last iteration remains, which is iLineSegmentColor = lay.xZoneColor(99,green,black). This color is then used to draw the line, which is x <= 99. So the line color must be green.
If there are only 100 iterations (or less than 1000), I would use (in C#):
for (int i = 0; i < yData.Length - 1; ++i)
{
//One line segment
LineLayer layer = c.addLineLayer(new double[] { yData[i], yData[i + 1] }, myColors[i]);
layer.setXData(new double[] {i, i + 1});
}
Hope this can help.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on May-18-2011 02:09 |
|
Peter,
Thanks for the reply.
Instead of adding a new XY line layer, can this be done by adding a new dataset for each point on the same Line layer?
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on May-18-2011 19:01 |
|
Hi Jaideep,
All data sets in a LineLayer must have the same x-coordinates. For your case, the line segments have different x-coordinates, so it is better to use different line layers. It is OK to have a few thousand layers. The overhead for a layer is quite small.
Hope this can help.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on May-21-2011 03:18 |
|
Peter,
While adding extra layers for each point would be better, our current architecture does not lend well to that scenario.
Is there a way we can do this by adding extra datasets to the same layer? Please advise.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on May-22-2011 12:48 |
|
Hi Jaideep,
Yes. You can do this by Chart.NoValue insertions. But this would become inefficient for large data sets (above a few hundreds), as the majority of the data points would be Chart.NoValue (which means your code would insert a large number of Chart.NoValue points to the datasets).
double[] buffer = new double[yData.Length];
buffer[0] = yData[0];
for (int i = 1; i < buffer.Length; ++i) buffer[i] = Chart.NoValue;
for (int i = 0; i < yData.Length - 1; ++i)
{
buffer[i + 1] = yData[y + 1];
layer.addDataSet(buffer, myColors[i]);
buffer[i] = Chart.NoValue;
}
Hope this can help.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on Nov-11-2011 05:04 |
|
Peter,
You had provided this solution a few months ago.
It works fine when the layer is a line layer, but when the layer in question is a spline one, it renders it as a line layer (since this method draws just one part of the entire layer at one time).
Is there a way to make this work for the spline chart too?
Please let me know.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on Nov-12-2011 01:41 |
|
Hi Jaideep,
For a spline, a segment between two points depend on the two points, as well as the points immediately before and after the two points.
So for spline, you need to keep 4 points per color. May be you can try:
double[] buffer = new double[yData.Length];
for (int i = 3; i < buffer.Length; ++i) buffer[i] = Chart.NoValue;
for (int i = 0; i < 3; ++i)
if (yData.Length > i) buffer[i] = yData[i];
for (int i = 0; i < yData.Length - 1; ++i)
{
if (i + 2 < yData.Length) buffer[i + 2] = yData[i + 2];
layer.addDataSet(buffer, c.xZoneColor(i, c.xZoneColor(i + 1, myColors[i], Chart.Transparent), Chart.Transparent));
if (i > 0) buffer[i - 1] = Chart.NoValue;
}
*** NOTE ***: The above assumes your data points are not using x-coordinates (no setXData). Otherwise, please replace the xZoneColor to:
c.xZoneColor(xData[i], c.xZoneColor(xData[i + 1], myColors[i], Chart.Transparent), Chart.Transparent));
Hope this can help.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on Nov-17-2011 07:34 |
|
Peter,
Thanks for the suggestion.
While the line chart code seems fine, this spline chart code works intermittently. In some scenarios it gives multiple lines drawn on the chart, so i am not sure if this is a good way to implement multiple line styles on a spline chart.
Would you know of a better way to do that? Please let me know.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on Nov-18-2011 03:39 |
|
Hi Jaideep,
If you think there are extra lines in your chart, you may try to trace the code to see where the lines come from. If you like, you may attach the abnormal chart, and also the exact charting code you are using. (Please include the exact and complete charting code, as the issue may or may not be related to the multi-color part of the code). I will try to diagnose the problem.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on Nov-18-2011 03:57 |
|
Peter,
Thanks for the reply.
Here is some further information. When i use the suggested code on a spline chart with no 'scaling', it works fine but when i use scaling like 'Linear Time Scale' in this case, the chart image is weird. In this particular scenario it was giving me multiple lines, and now it is simply returning a blank image.
I have attached the same chart without and with 'Linear Time Scale' applied to the x-axis, this seems to interfere with the code logic that you suggested for a spline chart.
(Time scale does not mess up the standard line chart though).
Also, i have attached the snippet of code that adds the color and multiple datasets to the spline layer.
thanks,
Jaideep.
|
|
SplineCode.txt |
---|
If sChartType = "Spline" Then
bAddFinalDataSet = False
'Dim htLineStl As Hashtable = setLineStyleAndColors(nlLayerData, eleLayer)
Dim ihtCt As Integer = Nothing
Dim iNewColor As Integer = GetColorFromElement(eleLayer, , &HFF)
Dim iNewPattern As Integer = getDashStyle(st.sGetAttribute(eleLayer, "LineStyle"))
'Set up New individual label array...14349
Dim yDataNew As Double() = New Double(yData.Length - 1) {}
For iLineCol As Integer = 3 To yDataNew.Length - 1
yDataNew(iLineCol) = Chart.NoValue
Next
For iLineCol As Integer = 0 To 2
If yData.Length > iLineCol Then
yDataNew(iLineCol) = yData(iLineCol)
End If
Next
' Loop entire data set not just the entries in the hash table.14349
For ihtCt = 0 To yData.Length - 2
Dim mLineInfo As New ChartStyleInfo()
mLineInfo = htLineStl(ihtCt)
If Not IsNothing(mLineInfo) Then
Dim sNewColor As String = mLineInfo.LineColor
If sNewColor.Length > 0 Then
iNewColor = GetColorFromString(sNewColor, 0)
End If
Dim sLinePattern As String = mLineInfo.LineStyle
If sLinePattern.Length > 0 Then
iNewPattern = getDashStyle(sLinePattern)
End If
' Get the color..
iFinalLineColor = lay.xZoneColor(mLineInfo.DataPoint, Chart.Transparent, lay.xZoneColor(mLineInfo.DataPoint + 1, c.dashLineColor(iNewColor, iNewPattern), Chart.Transparent))
Else
iFinalLineColor = GetColorFromElement(eleLayer, , &HFF)
End If
'individual dataset for each line segment...
If (ihtCt + 2) < yData.Length Then
yDataNew(ihtCt + 2) = yData(ihtCt + 2)
End If
ds = lay.addDataSet(yDataNew, iFinalLineColor)
If ihtCt > 1 Then
yDataNew(ihtCt - 1) = Chart.NoValue
End If
Next
End If
|
| |
Re: xZoneColor issue. |
Posted by Peter Kwan on Nov-19-2011 00:54 |
|
Hi Jaideep,
In your code, I see that you use:
lay.xZoneColor(mLineInfo.DataPoint, Chart.Transparent, lay.xZoneColor(mLineInfo.DataPoint + 1, c.dashLineColor(iNewColor, iNewPattern), Chart.Transparent))
The above is unlikely to work if you are using "Linear Time Scale" (that is, if you have called lay.setXData to set the x-coordinates of the data points). I am not too sure what is mLineInfo.DataPoint mean. It may be an integer representing the index of the data point, or it may be the "date/time" x-coordinate of the data point. In either case, "mLineInfo.DataPoint + 1" is not correct, as it is not the x-coordinate of the next data point.
As mentioned in my previous message, if x-coordinates are used, the code should be:
c.xZoneColor(xData[i], c.xZoneColor(xData[i + 1], myColors[i], Chart.Transparent), Chart.Transparent));
The xData[i] means the x-coordinate of the current point, and the xData[i + 1] means the x-coordinate of the next point. Note that xData[i + 1] is in general not the same as xData[i] + 1.
Please kindly let me know if the above can solve the problem.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on Nov-22-2011 01:11 |
|
Peter,
Thanks for the reply.
I understand that i would need to set xData(i) and xData(i+1) etc to make this work.
But c.xZoneColor(xData(i),....) requires that xData(i) be a double value. In case of linear time this value will be a datetime value and that won't work.
Is there something obvious that i am missing here?
Please let me know.
thanks,
Jaideep. |
Re: xZoneColor issue. |
Posted by Peter Kwan on Nov-22-2011 16:46 |
|
Hi Jaideep,
I see. You may try:
c.xZoneColor(Chart.CTime(xData[i]), c.xZoneColor(Chart.CTime(xData[i + 1]), myColors[i], Chart.Transparent), Chart.Transparent));
In general, if the ChartDirector API requires a double, but your actual data type is DateTime, you may use Chart.CTime to convert the DateTime to double.
Hope this can help.
Regards
Peter Kwan |
Re: xZoneColor issue. |
Posted by Jaideep on Feb-16-2012 03:09 |
|
Hi Peter.
Thanks for the suggestions for both the Line and Spline charts.
I have a related question.
The solution you provided for the line chart -
"double[] buffer = new double[yData.Length];
buffer[0] = yData[0];
for (int i = 1; i < buffer.Length; ++i) buffer[i] = Chart.NoValue;
for (int i = 0; i < yData.Length - 1; ++i)
{
buffer[i + 1] = yData[y + 1];
layer.addDataSet(buffer, myColors[i]);
buffer[i] = Chart.NoValue;
}
"
is a workaround, where we are adding additional datasets to the same layer.
My question was regarding the tooltips.
Normally i use lay.setHTMLImageMap("", "", "TITLE='{dsdiField0}'"), but in this case with multiple datasets, what is a good way to set the right title attribute?
thanks. |
Re: xZoneColor issue. |
Posted by Peter Kwan on Feb-16-2012 23:34 |
|
Hi Jaideep,
The way I normally used is to put each line in its own layer. For example, if you have two lines, you use two line layers.
So for one line, you may use use:
Layer *layer = c->addLineLayer();
layer->setXData(myXData);
layer->addExtraField(myToolTips);
layer->setHTMLImageMap("". "". "TITLE='{field0}'");
double[] buffer = new double[yData.Length];
buffer[0] = yData[0];
for (int i = 1; i < buffer.Length; ++i) buffer[i] = Chart.NoValue;
for (int i = 0; i < yData.Length - 1; ++i)
{
buffer[i + 1] = yData[y + 1];
layer.addDataSet(buffer, myColors[i]);
buffer[i] = Chart.NoValue;
}
If you have another line, please repeat the above code to add another line layer.
Hope this can help.
Regards
Peter Kwan |
|