Page 1 of 1

AreaSeries: different area colors above or under origin valu

Posted: Fri Apr 29, 2005 1:17 pm
by 8441073
Hello,
I have a TAreaSeries, and I want different area colors for values above or under the "origin" value of the chart.

I can explain what I wish with an example.

I set my TAreaSeries chart origin to 200. I want a green color for areas above 200, and red color for areas under 200, as in the figure below:
Image

Unfortunately, I obtain the follow:
Image

For my purpose, I used the OnAfterAdd event:

Code: Select all

if Sender.YValues[ValueIndex] > 200 then
   Sender.ValueColor[ValueIndex] := clGreen
else
   Sender.ValueColor[ValueIndex] := clRed;
As you can see, there are wrong coloured part, when passing from "above" to "under" the origin and vice-versa.
Is there any solution, using just one series, to get what I want?

I'm using TeeChartPro v 7.02
Thank you

Posted: Fri Apr 29, 2005 3:07 pm
by narcis
Hello NoName,

The images you posted are not displayed, maybe there's an error in the URL or they are to big. If you want you cant post your files at [url]news://www.steema.net/steema.public.attachments[/url] newsgroup.

In TAreaSeries, an area is determined by two values. The first one corresponds to previous area last value while the last value is the one which determines the area value and thus it's color.

To get this kind of behaviour you could add a dummy zero value at the beginning of the series as done in the code below:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
    Series1.Add(0,'',clYellow);
    Series1.Add(250,'',clYellow);
    Series1.Add(150,'',clYellow);
    Series1.Add(250,'',clYellow);
    Series1.Add(100,'',clYellow);
end;

procedure TForm1.Series1AfterAdd(Sender: TChartSeries;
  ValueIndex: Integer);
begin
  if Sender.YValues[ValueIndex] > 200 then
   Sender.ValueColor[ValueIndex] := clGreen
  else
   Sender.ValueColor[ValueIndex] := clRed;
end;
In case you wanted staired area style you could also use TBarSeries (setting Series1.BarWidthPercent:=100) or THistogramSeries.

Posted: Mon May 02, 2005 8:11 am
by 8441073
Hello, Narcis,

thank you for your interest in my problem, but I hope you can see the pictures, to better clarify my goal.

The image links are correct, and the picture size is 5 Kb each. Maybe when you saw my message, the server was temporarly down (A.K.A. Murphy's law).

Please try again. As you suggested, I posted images on newsgroup steema.public.attachments

Thank you
Regards

Posted: Mon May 02, 2005 12:45 pm
by Marjan
Hi.

The OnAfterAdd code looks fine ... but the problem is the coloring for area section is *always* done from for range between two points in series y values chart list. In your case, area series is constructed from four sections:
x=[0,1], y=[0,250] (section 1)
x=[1,2], y=[250,150] (section 2)
x=[2,3], y=[150,250] (section 3)
x=[3,4], y=[250,100] (section 4)
Now, each of these sections can be colored only with single color which you define in series OnAfterAdd event, so four segments are colored to:
segment 1 = green (0<200)
segment 2 = red (250 > 200)
segment 3 = green (150 < 200)
segment 4 = red (250 > 200)
Moving the YOrigin to 200 does not change number of section so you're still left with four segments and the same colors (as your images show). Solutions:
1) Split segments so that "negative" value will be colored differently from "positive" value. In your case, you have to insert the points at every position where area line crosses y=200 horizontal line:

Code: Select all

    Series1.AddXY(0,0,'');
    // need a point at y=200, x = ... ? calculate it
    // y-y1=k(x-x1) => (y-y1)/k + x1 = x
    // k= (250-0)(1-0) = 250, y1 = 0, x1= 0
    // (200-0)/250 + 0 = x => x = 200/250 = 0.8
    Series1.AddXY(0.8,200); // << inserted
    Series1.AddXY(1,250,'');
    // need another point between 1 and 2 .. use the same approach
    // k=-100, y1=250, x1= 1
    // x =-(200-250)/100 + 1 = 0.5 + 1 = 1.5
    Series1.AddXY(1.5,200); // << inserted
    Series1.AddXY(2,150,'');
    // one more between 2 and 3
    // k=100, y1=150, x1= 2
    // x =(200-150)/100 + 2 = 0.5 + 2 = 2.5
    Series1.AddXY(2.5,200); // << inserted
    Series1.AddXY(3,250,'');
    // one more between 3 and 4
    // k=-150, y1=250, x1= 3
    // x =-(200-250)/150 + 3 = 0.3333 + 3 = 3.3333
    Series1.AddXY(3.333,200); // << inserted
    Series1.AddXY(4,100,'');
I hope this example clarifies how area series segments are constructed and colored.

Posted: Tue May 03, 2005 9:33 am
by 8441073
Hello Marjan,

thank you for your kind answer to my problem, you well clarified everything.
So, using one AreaSeries, the solution is to calculate the X point between X values, and add it to the series.

Another solution, could be using two series, one just for "positive" values and another one just for "negative" ones, adding points of 0 value when needed.

That's OK, now it's our turn to choose the less effort solution.

Thank you.

Posted: Tue May 03, 2005 2:18 pm
by Marjan
Yes, the "two series" approach looks much easier and cleaner to implement <g>.