Recent

Author Topic: How to make the X scale show hour, minutes and seconds?  (Read 5715 times)

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
How to make the X scale show hour, minutes and seconds?
« on: July 21, 2014, 12:29:30 pm »
Haw can I make the X scale show hours, minutes and seconds?
For example if I have a curve starting from 0 to 10000 seconds, I want to have on the curve to have displayed 0:30:00; 1:000:00; 1:30:00...
10 000 seconds should be displayed as 2:26:40.
I remember that I tried this a long time ago and I had no success.  TAchart converted seconds to some absolute time... I do not remember exactly, but if someone tells me the straight way I will be thankful.
« Last Edit: July 21, 2014, 12:33:22 pm by paskal »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: How to make the X scale show hour, minutes and seconds?
« Reply #1 on: July 23, 2014, 03:33:26 pm »
I have some partial success.
The following code:
Code: [Select]
uses ... TAGraph, TAIntervalSources, TASeries, TAChartUtils, TACustomSource...


procedure TForm1.Button2Click(Sender: TObject);

var
  MyChart: TChart;
  MySeries: TLineSeries;
  MyScaleXMarks: TDateTimeIntervalChartSource;
  i:integer;
begin
  MyChart:= TChart.Create(Self);
  MyChart.Parent:= Self;
  MyScaleXMarks:=TDateTimeIntervalChartSource.Create(Self);
  MyScaleXMarks.Params.Count:=5;
  MyScaleXMarks.Params.Options:=[aipUseCount,aipUseNiceSteps];
  MyScaleXMarks.Steps:=[dtsHour,dtsMinute,dtsSecond,dtsMillisecond];
MyScaleXMarks.DateTimeFormat:='hh:mm:ss.ss';
  MyChart.BottomAxis.Marks.Format:='%2:s';
  MyChart.BottomAxis.Marks.Source:=MyScaleXMarks;

  MySeries:=TLineSeries.Create (MyChart);
  MyChart.AddSeries(MySeries);
  for i:= 0 to 3600 do
    MySeries.AddXY(i/(3600*24),5*sin(i/100));
end;
   
Scales are shown, but:
1. One X unit does not correspond to 1 sec, but to 3600*24 seconds, so I have to divide the X values.
2. Milliseconds are separated by a dot, instead of a comma, I wrote hh:mm:ss.ss by memory, maybe I did something wrong.
 
« Last Edit: July 29, 2014, 11:01:40 am by paskal »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: How to make the X scale show hour, minutes and seconds?
« Reply #2 on: July 23, 2014, 07:37:19 pm »
I must admit that I never fully understood what the TDateTimeIntervalChartSource does...

Usually, when I have special formatting requirements for axis labels I create the labels manually in a TListChartSource, then I have full control. The code below, for example, places labels, according to your selection, every minute, 2 minutes, 5 minutes, etc.

Code: [Select]
const
  ONE_MINUTE = 1.0/(24*60);

type
  TMinutesInterval = (mi1Min, mi2Min, mi5Min, mi10Min, mi15Min, mi20Min, mi30Min, mi60Min);

const
  Minutes: array[TMinutesInterval] of Word = (1, 2, 5, 10, 15, 20,30, 60);

procedure PopulateTimeSource(AMin, AMax: TTime; MinutesInterval: TMinutesInterval;
  AListSource: TListChartsource);
var
  t, dt: TTime;
  timeStr: String;
  hr, min, sec, ms: Word;
begin
  t := AMin;
  DecodeTime(t, hr, min, sec, ms);
  dt := ONE_MINUTE * Minutes[MinutesInterval];
  t := EncodeTime(hr, round(trunc(min/dt)*dt), 0, 0);

  AListSource.Clear;
  repeat
    timeStr := FormatDateTime('hh:nn:ss,zzz', t);
    AListSource.Add(t, t, timeStr);
    t := t + dt;
  until (t > AMax) and (abs(t-AMax)>ONE_MINUTE/60);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyChart: TChart;
  MySeries: TLineSeries;
  MyScaleXMarks: TListChartSource;
  i:integer;
begin
  MyChart:= TChart.Create(Self);
  MyChart.Parent:= Self;
  MyChart.Align := alClient;
  MyScaleXMarks := TListChartSource.Create(self);

  MyChart.BottomAxis.Marks.Style := smsLabel;
  MyChart.BottomAxis.Marks.Source:=MyScaleXMarks;

  MySeries:=TLineSeries.Create (MyChart);
  MyChart.AddSeries(MySeries);
  for i:= 0 to 10000 do
    MySeries.AddXY(i/(3600*24),5*sin(i/100));

  PopulateTimeSource(MySeries.GetXMin, MySeries.GetXMax, mi15Min, MyScaleXmarks);
end;               
       
                     
The only - sometimes severe - drawback of this code is that the label interval does not change when you zoom. To get this you have to consider also the extent of the x axis and select the minute interval accordingly, for example in the OnMouseUp event of the Zoomtool:

Code: [Select]
procedure TForm1.ZoomToolAfterMouseUp(ATool: TChartTool;
  APoint: TPoint);
var
  dt: double;
  mi: TMinutesInterval;
  MyChart: TChart;
begin
  MyChart := ATool.Chart;
  dt := (MyChart.LogicalExtent.b.x - Mychart.LogicalExtent.a.x) * 24;  // hours
  if dt > 5 then
    mi := mi60Min
  else if dt > 2 then
    mi := mi30Min
  else if dt > 1 then
    mi := mi15Min
  else if dt > 0.5 then
    mi := mi5min
  else
    mi := mi1min;

  PopulateTimeSource(MyChart.LogicalExtent.a.x, MyChart.LogicalExtent.b.x, mi,
    MyChart.BottomAxis.Marks.Source as TListChartSource);
end;   

Your specific question regarding the decimal point: No - the decimal point seems to be hardcoded (one thing I could change some time...). In the FormatDateTime code you can specifiy the decimal separator freely. But your symbol for the milliseconds is not correct: use a "z" instead of an "s" (http://www.freepascal.org/docs-html/rtl/sysutils/formatchars.html).

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: How to make the X scale show hour, minutes and seconds?
« Reply #3 on: July 29, 2014, 12:43:09 pm »
Thanks, I will try your code when I finish some tasks, that have come to be more urgent.

Usually, when I have special formatting requirements for axis labels I create the labels manually in a TListChartSource, then I have full control. The code below, for example, places labels, according to your selection, every minute, 2 minutes, 5 minutes, etc.
...
The only - sometimes severe - drawback of this code is that the label interval does not change when you zoom. To get this you have to consider also the extent of the x axis and select the minute interval accordingly, for example in the OnMouseUp event of the Zoomtool:

 
It might be a drawback, but it might be an advantage.

 

Your specific question regarding the decimal point: No - the decimal point seems to be hardcoded (one thing I could change some time...). In the FormatDateTime code you can specifiy the decimal separator freely. But your symbol for the milliseconds is not correct: use a "z" instead of an "s" (http://www.freepascal.org/docs-html/rtl/sysutils/formatchars.html).

Oddly, my windows occurred to have switched itself to decimal delimer dot :o
That is why I have dots on the left axis. As far for the bottom axis, I set MyScaleXMarks.DateTimeFormat:='hh:mm:ss,zz'; 
« Last Edit: July 30, 2014, 08:00:16 am by paskal »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

 

TinyPortal © 2005-2018