AreaSeries: different area colors above or under origin valu

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
NoName
Newbie
Newbie
Posts: 34
Joined: Fri Nov 15, 2002 12:00 am
Location: Italy

AreaSeries: different area colors above or under origin valu

Post by NoName » Fri Apr 29, 2005 1:17 pm

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

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Fri Apr 29, 2005 3:07 pm

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.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

NoName
Newbie
Newbie
Posts: 34
Joined: Fri Nov 15, 2002 12:00 am
Location: Italy

Post by NoName » Mon May 02, 2005 8:11 am

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

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Mon May 02, 2005 12:45 pm

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.
Marjan Slatinek,
http://www.steema.com

NoName
Newbie
Newbie
Posts: 34
Joined: Fri Nov 15, 2002 12:00 am
Location: Italy

Post by NoName » Tue May 03, 2005 9:33 am

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.
Regards

Marjan
Site Admin
Site Admin
Posts: 745
Joined: Fri Nov 07, 2003 5:00 am
Location: Slovenia
Contact:

Post by Marjan » Tue May 03, 2005 2:18 pm

Yes, the "two series" approach looks much easier and cleaner to implement <g>.
Marjan Slatinek,
http://www.steema.com

Post Reply