scale problem on bottom axis (overlap)

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
SteveP
Advanced
Posts: 132
Joined: Sun Sep 07, 2003 4:00 am

Post by SteveP » Fri Mar 11, 2005 2:44 pm

Perhaps an axis property NumberOfDisplayedLabels could be implemented ?

Also, I notice that the axis property Increment is a mininum value to be used. That is, sometimes the axis will display an increment that is greater than the specified Increment but is not an integer multiple of that Increment. If I specifiy 0.2 for the Increment, at times the increment may be shown as 0.5. Any way to force the displayed increment to be an integer multiple of the one specified so that in my example it would show as 0.4 or 0.8 or 1.0 etc /

Leroy Casterline
Newbie
Newbie
Posts: 50
Joined: Wed Mar 10, 2004 5:00 am

Post by Leroy Casterline » Tue May 10, 2005 9:43 pm

Marjan wrote:Hi, Leroy.

Using the latest TeeChart version (7.04) and the code bellow axis label increment value was not changed even when chart was scrolled. The trick is to set LabelsSeparation to 0 and force, regardless of possible overlaps, display of all labels.

Code: Select all

  Series1->FillSampleValues(5000);

  Series1->GetHorizAxis->LabelsSeparation = 0;
  Series1->GetHorizAxis->Increment = 200.0;
  Series1->GetHorizAxis->LabelsOnAxis := true;
  Series1->GetHorizAxis->RoundFirstLabel = true;
Hi, Marjan.

I’m back to trying to solve this problem again.

I think that the problem is that I must display X-Axis labels in two different formats. The actual values stored in the chart are sample numbers that start at 1 and increment by 1. Thus, in a typical chart my X-Axis values range from 1 to, perhaps, 2,000,000.

One of the X-Axis display formats is just the sample number as described above. The other format is time-based, with the sample number converted into microseconds or milliseconds, for example:

200 uS or 10000.200 mS

When I use your suggested settings with the time-based format, the labels overlap:

Image

When I use them with the sample count format, they work for small numbers, but the labels are sparser than I’d like:

Image

But if I change the increment value to 100, with larger sample count values they overlap:

Image

Setting LabelSeparation to various values doesn’t solve the problem either. For example, with LabelSeparation set to 10, the values between 100,000 and 1,000,000 display as a nearly continuous series of digits:

Image

Setting LabelSeparation to 20 results in the same display. If I set LabelSeparation to 30, the above range is displayed properly, but values between 10,000 and 100,000 are crowded too closely.

I tried creating a list of coordinates and labels in the OnDrawLabel event handler and setting Text to “” so that it wouldn’t display any labels. Then in the OnAfterDraw event, I looped through my list of labels and drew them with DrawAxisLabel so that I could skip labels as needed. This didn’t work because OnDrawLabel fired again when I called DrawAxisLabel.

Matters are complicated by the fact that the chart is resizable and the user can choose the number of points to display across the width of the chart.

I need to find some way to handle labeling properly for both my label formats. How can I accomplish this?

-Leroy

P.S. Last time I posted in this thread it took about 2 weeks to get an answer. I hope you will be able to respond more quickly this time.

SteveP
Advanced
Posts: 132
Joined: Sun Sep 07, 2003 4:00 am

Post by SteveP » Wed May 11, 2005 12:55 pm

>This didn’t work because OnDrawLabel fired again when I called >DrawAxisLabel.

Perhaps try to temporarily turn off that event firing, then do your change, then turn the event back on ?

chart1.OnGetAxisLabel := nil;
{
make changes to property that normally fires the bove event
}
chart1.OnGetAxisLabel := Chart1GetAxisLabel;

Leroy Casterline
Newbie
Newbie
Posts: 50
Joined: Wed Mar 10, 2004 5:00 am

Post by Leroy Casterline » Wed May 11, 2005 4:18 pm

9333098 wrote:>This didn’t work because OnDrawLabel fired again when I called >DrawAxisLabel.

Perhaps try to temporarily turn off that event firing, then do your change, then turn the event back on ?

chart1.OnGetAxisLabel := nil;
{
make changes to property that normally fires the bove event
}
chart1.OnGetAxisLabel := Chart1GetAxisLabel;
Thanks for the suggestion, Steve. I'd thought of that, but if I turn off the event, then TeeChart will be redrawing its labels directly (the event is where I set the label text to an empty string to prevent the chart's labels from showing).

The problem with the event firing is that when it fires, I add the label to my list of pending labels and, since it fires when I draw a pending label, I end up in an infinite loop - draw a label from my list, OnDrawLabel fires, I add another label to the list, etc. I guess I could set a flag when I drawing labels from my list that would be checked in OnDrawLabel to prevent a new list entry, but this is a rather ugly solution.

I also thought of setting Axis->Labels to false so the chart doesn't draw labels at all, but if I do that the chart doesn't reserve room for my labels and I also have to go to the work of computing label positions and drawing my X-Axis grid lines and ticks.

There's got to be a better solution!

-Leroy

Leroy Casterline
Newbie
Newbie
Posts: 50
Joined: Wed Mar 10, 2004 5:00 am

Post by Leroy Casterline » Thu May 19, 2005 9:20 pm

9336236 wrote:P.S. Last time I posted in this thread it took about 2 weeks to get an answer. I hope you will be able to respond more quickly this time.
It's been 9 days with no repsonse from Steema. Please?

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

Post by Marjan » Tue May 24, 2005 5:40 am

Hi, Leroy.
tried creating a list of coordinates and labels in the OnDrawLabel event handler and setting Text to “” so that it wouldn’t display any labels. Then in the OnAfterDraw event, I looped through my list of labels and drew them with DrawAxisLabel so that I could skip labels as needed. This didn’t work because OnDrawLabel fired again when I called DrawAxisLabel
In this case I'd manually calculate all axis labels needed for display and then repopulate chart each time it's drawn. This way you'll be able to fully control individual axis labels and even use variable increment. Here is an example (of course, you'll use more complex code <g>):

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var labels: Array of double;
  i: Integer;
begin
  Series1.FillSampleValues(2000);

  // example : show 7 labels
  SetLength(Labels,7);
  Labels[0] := 0;
  Labels[1] := 300;
  Labels[3] := 600;
  Labels[4] := 900;
  Labels[5] := 1400;
  Labels[6] := 1900;
  With Chart1.Axes.Bottom.Items do
  begin
    Clear;
    for i := 0 to High(Labels) do
      Add(Labels[i],FormatFloat('0.00 ys',Labels[i]));
  end;
end;
When chart size or axis increment changes, all you have to do is calculate best new labels and add repopulate the Axes.Bottom.Items. Using this approach you can fully control not only the axis labels, but axis increment and (if needed) additional axis label properties (like font, etc..).
Marjan Slatinek,
http://www.steema.com

Leroy Casterline
Newbie
Newbie
Posts: 50
Joined: Wed Mar 10, 2004 5:00 am

Post by Leroy Casterline » Tue May 24, 2005 5:15 pm

Marjan wrote:Hi, Leroy.
tried creating a list of coordinates and labels in the OnDrawLabel event handler and setting Text to “” so that it wouldn’t display any labels. Then in the OnAfterDraw event, I looped through my list of labels and drew them with DrawAxisLabel so that I could skip labels as needed. This didn’t work because OnDrawLabel fired again when I called DrawAxisLabel
In this case I'd manually calculate all axis labels needed for display and then repopulate chart each time it's drawn. This way you'll be able to fully control individual axis labels and even use variable increment. Here is an example (of course, you'll use more complex code <g>):

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var labels: Array of double;
  i: Integer;
begin
  Series1.FillSampleValues(2000);

  // example : show 7 labels
  SetLength(Labels,7);
  Labels[0] := 0;
  Labels[1] := 300;
  Labels[3] := 600;
  Labels[4] := 900;
  Labels[5] := 1400;
  Labels[6] := 1900;
  With Chart1.Axes.Bottom.Items do
  begin
    Clear;
    for i := 0 to High(Labels) do
      Add(Labels[i],FormatFloat('0.00 ys',Labels[i]));
  end;
end;
When chart size or axis increment changes, all you have to do is calculate best new labels and add repopulate the Axes.Bottom.Items. Using this approach you can fully control not only the axis labels, but axis increment and (if needed) additional axis label properties (like font, etc..).
How do I know what values the labels should have? In other words, how do I know where the chart has placed the grid lines and ticks? There doesn't seem to be any way to specify them - increment and separation seem to be more suggestions than anything.

Where (in what event handler) do I do this?

As I said:
tried creating a list of coordinates and labels in the OnDrawLabel event handler and setting Text to “” so that it wouldn’t display any labels. Then in the OnAfterDraw event, I looped through my list of labels and drew them with DrawAxisLabel so that I could skip labels as needed. This didn’t work because OnDrawLabel fired again when I called DrawAxisLabel
Also, how do I prevent the chart from drawing its own labels while saving room for me to draw my own? If I disable labels entirely then the chart draws without leaving room for me to draw the labels.

Post Reply