Overlapping series on the X axis

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
cristian
Newbie
Newbie
Posts: 3
Joined: Tue Sep 23, 2014 12:00 am

Overlapping series on the X axis

Post by cristian » Thu Jun 18, 2015 2:41 pm

Good morning!
I'm working on a project in Delphi 7 where I use TChart (2014 version) with TFastLine series to view computer performance queries related to CPU, memory and disk. In the performance filters of the three options, it can be selected one or more computers by the user for data collection. The graphic works perfectly when there’s only one computer selected. However, when the user choose more than one computer, each one is represented by an TChart serie where the axis Y shows the percentage of performance item and the axis X shows the date/time. The problem appears on the axis X witch each computer adds the date/time information again, covering the information of the previous series. The best way would be that the data of the axis X were filled only once, independent of the computer number or date/time period.

The following image shows how the information is appearing.

Image

I look forward solution suggestions.
Thank you.

Alan
Newbie
Newbie
Posts: 5
Joined: Thu Mar 01, 2007 12:00 am

Re: Overlapping series on the X axis

Post by Alan » Thu Jun 18, 2015 3:52 pm

Same problem here. Just stumbled across your post while looking for answers. Using XE7 with the included version of TChart.

It happens when there is more than one chartseries. If you use the OnGetAxisLabel event, and clear the LabelText whenever the Series.SeriesIndex <> 0 for example, this fixes it (in a way). But this also leads to labels not being drawn at all if the other series have data past the end of the first series max X value.

This mimics another older post here that relates to the Y-Axis.

http://www.teechart.net/support/viewtop ... 48&p=48160

cristian
Newbie
Newbie
Posts: 3
Joined: Tue Sep 23, 2014 12:00 am

Re: Overlapping series on the X axis

Post by cristian » Thu Jun 18, 2015 4:50 pm

This solution I had already tested, though we have exactly the problem you mentioned. If we have series with different values of X, in this case, they would be chart pieces without the label on the X axis. Is there any other solution to this problem?

Yeray
Site Admin
Site Admin
Posts: 9533
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Overlapping series on the X axis

Post by Yeray » Fri Jun 19, 2015 9:59 am

Hello,

I'm not sure about how are you exactly populating your series.
I guess you are adding values and labels to both series, is that correct?
I understand one of the series has more values than the other, but do the XValues of both series share the same increment? If not, the labels of what series would you like to show?
It would be helpful if you could arrange a simple example project we can run as-is to reproduce the situation here.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

cristian
Newbie
Newbie
Posts: 3
Joined: Tue Sep 23, 2014 12:00 am

Re: Overlapping series on the X axis

Post by cristian » Fri Jun 19, 2015 2:22 pm

Hi! You understood exactly my problem. I'm really inserting labels in all series and the series have different values of X from each other. The X values of the series are not incremented accordingly. I would like to show in the lower graph the label and the higher value (regardless of which series may be). Between the lowest and the highest value I want the labels are automatically generated for the user to orient the chart. Is there a feature to help with this? I will set up a project so you can reproduce the problem. Thank you for attention.

Alan
Newbie
Newbie
Posts: 5
Joined: Thu Mar 01, 2007 12:00 am

Re: Overlapping series on the X axis

Post by Alan » Fri Jun 19, 2015 6:07 pm

I'll echo Cristians statement - yes when the different series are populated with different X-Values.

In our case, we have data with timestamps. One series is of temperature data collected at various intervals over a time period. The other series is another temperature probe's data collected at various intervals during an overlapping time period. The X Values do not correspond exactly to each other.

We are not adding label data to our series, just the values.

When the axis are drawn, it appears that the labels on the axis are obtained by looking at all of the series. That is when a label will get drawn that overlaps another one. Our trends will look just like Cristian's where the x-axis labels are jumbled. And the axis grid doesn't appear at consistent intervals - there will be an extra one here and there that causes the jumbled labels.

Yeray
Site Admin
Site Admin
Posts: 9533
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Overlapping series on the X axis

Post by Yeray » Mon Jun 22, 2015 8:39 am

Hi,
cristian wrote:I'm really inserting labels in all series and the series have different values of X from each other. The X values of the series are not incremented accordingly. I would like to show in the lower graph the label and the higher value (regardless of which series may be). Between the lowest and the highest value I want the labels are automatically generated for the user to orient the chart. Is there a feature to help with this?
Having labels in your series, if the bottom axis LabelStyle is set to talAuto as per default, it will show all the series labels. In that case you should implement some anti overlapping system.
Find below a simple example that reproduces the problem and fixes it. Disable OnGetAxisLabel event to see the problem.

Code: Select all

uses Series;

procedure TForm1.FormCreate(Sender: TObject);
var i, j: Integer;
begin
  Chart1.View3D:=false;

  Chart1.AddSeries(TFastLineSeries).FillSampleValues(20);
  Chart1.AddSeries(TFastLineSeries).FillSampleValues(25);

  for i:=0 to 1 do
    with Chart1[i] as TFastLineSeries do
      for j:=0 to Chart1[i].Count-1 do
        Labels[j]:=FormatFloat('#0.##', Chart1[i].XValue[j]);

  Chart1.OnGetAxisLabel:=AxisGetAxisLabel;
end;

procedure TForm1.AxisGetAxisLabel(Sender:TChartAxis; Series:TChartSeries; ValueIndex:Integer; var LabelText:String);
var i, lXPos, lWidth, tmpWidth: Integer;
    XVal: Double;
    item: TAxisItem;
    lRect, tmpRect: TRect;
begin
  if (Sender=Chart1.Axes.Bottom) and
     (Series<>nil) and (ValueIndex>-1) and (ValueIndex<Series.Count) then
  begin
    XVal:=Series.XValue[ValueIndex];
    lXPos:=Sender.CalcXPosValue(XVal);
    lWidth:=Chart1.Canvas.TextWidth(LabelText);
    lRect:=Rect(lXPos-(lWidth div 2), 0, lXPos-(lWidth div 2)+lWidth, 10);

    for i:=0 to Sender.Items.Count-1 do
    begin
      item:=Sender.Items[i];
      tmpWidth:=Chart1.Canvas.TextWidth(item.Text);
      tmpRect:=Rect(item.LabelPos-(tmpWidth div 2), 0, item.LabelPos-(tmpWidth div 2)+tmpWidth, 10);
      if (TeeRectIntersects(lRect, tmpRect)) then
      begin
        LabelText:='';
        exit;
      end;
    end;
  end;
end;
Another alternative is to force the axis to show values instead of the series labels:

Code: Select all

Chart1.Axes.Bottom.LabelStyle:=talValue;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Yeray
Site Admin
Site Admin
Posts: 9533
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Overlapping series on the X axis

Post by Yeray » Mon Jun 22, 2015 8:55 am

Hi Alan,
Alan wrote:I'll echo Cristians statement - yes when the different series are populated with different X-Values.

In our case, we have data with timestamps. One series is of temperature data collected at various intervals over a time period. The other series is another temperature probe's data collected at various intervals during an overlapping time period. The X Values do not correspond exactly to each other.

We are not adding label data to our series, just the values.

When the axis are drawn, it appears that the labels on the axis are obtained by looking at all of the series. That is when a label will get drawn that overlaps another one. Our trends will look just like Cristian's where the x-axis labels are jumbled. And the axis grid doesn't appear at consistent intervals - there will be an extra one here and there that causes the jumbled labels.
Your case is slightly different.
I'm trying to reproduce your situation without success with the following code. I'm adding points in two series with random X values and the bottom axis shows no overlapping labels by default:

Code: Select all

uses Series, dateUtils;

procedure TForm1.FormCreate(Sender: TObject);
var i, j: Integer;
    tmpValue: Double;
    tmpDateStart, tmpDate: TDateTime;
begin
  Chart1.View3D:=false;

  tmpDateStart:=Now;

  for i:=0 to 1 do
    with Chart1.AddSeries(TFastLineSeries) as TFastLineSeries do
    begin
      XValues.DateTime:=true;

      tmpDate:=tmpDateStart;
      tmpValue:=100+random*10;

      AddXY(tmpDate, tmpValue);
      for j:=1 to 20-1 do
      begin
        tmpDate:=IncDay(tmpDate, Round(random*5+1));
        tmpValue:=YValue[j-1]+random*10-5;

        AddXY(tmpDate, tmpValue);
      end;
    end;
end;
Could you please arrange a simple example we can run as-is to reproduce the problem here?
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Alan
Newbie
Newbie
Posts: 5
Joined: Thu Mar 01, 2007 12:00 am

Re: Overlapping series on the X axis

Post by Alan » Tue Jun 23, 2015 1:00 pm

Hi Yeray,

I would add these lines:

Code: Select all

Chart1.BottomAxis.LabelStyle := talPointValue;
Chart1.OnGetAxisLabel := Chart1GetAxisLabel;
You can simply do something like this in the GetAxisLabel event:

Code: Select all

  if Sender.Horizontal then
    if ValueIndex >= 0 then
        begin
              d := Series.XValue[ValueIndex];
              LabelText := LabelText + FormatDateTime('h:nn:ss', frac(d));
        end

Does that cause the behavior I'm reporting?

Edit - you don't even have to use the GetAxisLabel event. Setting the labelstyle property should suffice

I need to use the GetAxisLabel event though to make the necessary formatting for our displays. Therefore I have to set the LabelStyle property.

Yeray wrote:Hi Alan,
Alan wrote:I'll echo Cristians statement - yes when the different series are populated with different X-Values.

In our case, we have data with timestamps. One series is of temperature data collected at various intervals over a time period. The other series is another temperature probe's data collected at various intervals during an overlapping time period. The X Values do not correspond exactly to each other.

We are not adding label data to our series, just the values.

When the axis are drawn, it appears that the labels on the axis are obtained by looking at all of the series. That is when a label will get drawn that overlaps another one. Our trends will look just like Cristian's where the x-axis labels are jumbled. And the axis grid doesn't appear at consistent intervals - there will be an extra one here and there that causes the jumbled labels.
Your case is slightly different.
I'm trying to reproduce your situation without success with the following code. I'm adding points in two series with random X values and the bottom axis shows no overlapping labels by default:

Code: Select all

uses Series, dateUtils;

procedure TForm1.FormCreate(Sender: TObject);
var i, j: Integer;
    tmpValue: Double;
    tmpDateStart, tmpDate: TDateTime;
begin
  Chart1.View3D:=false;

  tmpDateStart:=Now;

  for i:=0 to 1 do
    with Chart1.AddSeries(TFastLineSeries) as TFastLineSeries do
    begin
      XValues.DateTime:=true;

      tmpDate:=tmpDateStart;
      tmpValue:=100+random*10;

      AddXY(tmpDate, tmpValue);
      for j:=1 to 20-1 do
      begin
        tmpDate:=IncDay(tmpDate, Round(random*5+1));
        tmpValue:=YValue[j-1]+random*10-5;

        AddXY(tmpDate, tmpValue);
      end;
    end;
end;
Could you please arrange a simple example we can run as-is to reproduce the problem here?

Yeray
Site Admin
Site Admin
Posts: 9533
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Overlapping series on the X axis

Post by Yeray » Thu Jun 25, 2015 9:14 am

Hello Alan,

TalPointValue LabelStyle shows a label for each point in a series preventing the labels overlapping for that series; but I'm afraid it doesn't consider the labels drawn for the other series. So, having several series with different XValues has chances of end in overlapping labels.
However, the same control I suggested to Cristian also works with talPointValue. Here it is a simple but complete example:

Code: Select all

uses Series, dateUtils;

procedure TForm1.FormCreate(Sender: TObject);
var i, j: Integer;
    tmpValue: Double;
    tmpDateStart, tmpDate: TDateTime;
begin
  Chart1.View3D:=false;

  tmpDateStart:=Now;

  for i:=0 to 1 do
    with Chart1.AddSeries(TLineSeries) as TLineSeries do
    begin
      Pointer.Visible:=true;
      XValues.DateTime:=true;

      tmpDate:=tmpDateStart;
      tmpValue:=100+random*10;

      AddXY(tmpDate, tmpValue);
      for j:=1 to 20-1 do
      begin
        tmpDate:=IncDay(tmpDate, Round(random*5+1));
        tmpValue:=YValue[j-1]+random*10-5;

        AddXY(tmpDate, tmpValue);
      end;
    end;

  Chart1.Axes.Bottom.LabelStyle:=talPointValue;
  Chart1.OnGetAxisLabel:=Chart1GetAxisLabel;
end;

procedure TForm1.Chart1GetAxisLabel(Sender:TChartAxis; Series:TChartSeries;
                             ValueIndex:Integer; var LabelText:String);
var i, lXPos, lWidth, tmpWidth: Integer;
    XVal: Double;
    item: TAxisItem;
    lRect, tmpRect: TRect;
begin
  if (Sender.Horizontal) and (Series<>nil) and (ValueIndex>=0) and
     (ValueIndex<Series.Count) then
  begin
    XVal:=Series.XValue[ValueIndex];
    lXPos:=Sender.CalcXPosValue(XVal);
    LabelText:=LabelText + ' ' + FormatDateTime('h:nn:ss', frac(XVal));
    lWidth:=Chart1.Canvas.TextWidth(LabelText);
    lRect:=Rect(lXPos-(lWidth div 2), 0, lXPos-(lWidth div 2)+lWidth, 10);

    for i:=0 to Sender.Items.Count-1 do
    begin
      item:=Sender.Items[i];
      tmpWidth:=Chart1.Canvas.TextWidth(item.Text);
      tmpRect:=Rect(item.LabelPos-(tmpWidth div 2), 0, item.LabelPos-(tmpWidth div 2)+tmpWidth, 10);
      if (TeeRectIntersects(lRect, tmpRect)) then
      begin
        LabelText:='';
        exit;
      end;
    end;
  end;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Alan
Newbie
Newbie
Posts: 5
Joined: Thu Mar 01, 2007 12:00 am

Re: Overlapping series on the X axis

Post by Alan » Thu Jun 25, 2015 3:25 pm

Thank you. Your solution works for me.

Post Reply