|
Need extended axis time formats |
Posted by David Wilson on Jun-07-2011 22:03 |
|
Our application has special requirements for axis time formats, but I don't
think they are too outlandish.
For starters, we need to show our times in an hh:mm:ss format where
the hours do not wrap at 24 hours. For example, a 2-hour period
needs to display as "02:00:00", a 2-day period as "48:00:00", and a
1-week period as "168:00:00". Notice the hours must be left-zero-padded
to 2 digits if possible.
I looked under "Parameter Substitution and Formatting" and couldn't
find exactly what I needed. I was able to get what I wanted using the
complicated format
{={value}/36000-{value}/36000%1}{={value}/3600%10-{value}/3600%1}:{value|nn:ss}
If I pass time value 123456.0 to this format, I see 34:17:36 as required.
This would be easier if ChartDirector supported non-wrapping time formats.
For example, there could be formats td, th, tn, ts for total days, hours, minutes
and seconds. For time value value 123456.0, these formats would display as
td = 2
th = 34
tn = 2057
ts = 123456
tdd = 02
thh = 34
tnn = 2057
tss = 123456
My required labels would have the simple format {value|thh:nn:ss}
A second problem I have encountered is that I need to show negative time
values on the axis.
This presents two problems.
First, if you use Axis::setDateScale(lowerLimit, upperLimit) with lowerLimit < 0,
it resets lowerLimit to 0, throwing away negative time values. I was able to get
around by using setLinearScale().
However, negative time values do not format correctly on the axis. For example,
if you display time value -12345.0 using {value|hh:nn:ss}, you get -03:-25:-45.
I could not find a solution using the existing formats.
However, I can propose the following solution:
Perhaps ChartDirector could add "non-wrapping" time formats. For example, there
could be formats td, th, tn, and ts for total days, hours, minutes and seconds.
There would be variants tdd, thh, tnn, tss for 2-digit zero-padded values.
Some formats are wrapping formats, because the values wrap at some maximum
value. For example, the hh format wraps at 24 hours, nn format at 60 minutes,
etc. My proposed formats thh, tnn, tss are non-wrapping, they have no upper limit.
I propose that wrapping formats always be computed from the absolute value of
the time value. For example, if passed time value -12345.0, compute hh, nn, ss
from 12345.0.
For non-wrapping formats, compute from the signed value. For example, if passed
time value -12345.0, compute thh, tnn, tss from the signed value -12345.0.
So for time value -12345.0, we get
thh = -03, since it is computed from signed value -12345.0
nn = 25 (not -25), since it is computed from absolute value 12345.0
ss = 45 (not -45), since it is computed from absolute value 12345.0
In this way, if we format time value -12345.0 using {value|thh:nn:ss},
we get -03:25:45, as desired. |
Re: Need extended axis time formats |
Posted by Peter Kwan on Jun-08-2011 03:26 |
|
Hi David,
Thanks a lot for your valuable suggestion for the new format quotes for non-wrapping date/time formatting. I think it is very useful. We have seen a number of cases that requires non-wrapping formatting of some values (it can be minutes, hours, or days). The new format quotes certainly would make it much easier to achieve. I have just entered this into our feature list to be implemented in a future version of ChartDirector.
For your current case, for negative date/time formatting, there is method to work around by using custom date/time formatting. There are two methods:
(a) ..... create chart as usual .....
//after entering all the data and configures the chart, auto-scale the axis
c->layout();
//get the ticks
DoubleArray ticks = c->xAxis()->getTicks();
for (int i = 0; i < ticks.len; ++i) {
std::string label = customFormatting(ticks[i]);
c->addLabel(ticks[i], label.c_str());
}
In the above, customFormatting is a custom formatting function written by you that accepts a double precision number, and return a text string (std::string or a valid "const char *").
or
(b) StringArray labels = .... create an array of text strings as the labels ....
c->xAxis()->setLinearScale(startValue, endValue, labels);
Hope this can help.
Regards
Peter Kwan |
Re: Need extended axis time formats |
Posted by David Wilson on Jun-10-2011 21:39 |
|
I implemented your suggested solution from the previous message. I was able to place explicitly-formatted negative time values on the axis, however, I ran into another problem. It turns out that while Axis::setDateScale() places tickmarks at reasonable time intervals (e.g, 10 seconds, 30 seconds, 1 minute), Axis::setLinearScale() places tickmarks at awkward time intervals (e.g. 50 seconds, 3:20, etc.). I played with Axis::setTickDensity(), but it didn't help.
So, to summarize, if I use Axis::setDateScale(), negative time values are removed from the axis, if I use Axis::setLinearScale(), tickmarks apeear in awkward places for a time axis.
For now I will live with not showing negative time values.
Perhaps in the future you can implement negative time label formats and modify Axis::setDateScale() to allow negative time values. |
Re: Need extended axis time formats |
Posted by Peter Kwan on Jun-10-2011 22:48 |
|
Hi David,
Yes. If auto-scaling is used to set up the labels, in linear mode, the labels will be separated by something like 10, 20, 50, 100, .... In date/time mode, the labels will be separated by something like 10, 15, 30, 60, 3600 (1 hour), 86400 (1 day), etc..
For your case, there are two methods:
(a) Instead of using auto-scaling to come up with the labels, specify the label increment with your own code, like:
//60 seconds per label
c->xAxis()->setLinearScale(-300, 300, 60);
(b) Instead of using negative time, change it to positive time by adding a suitable constant, like adding 1000 years (that is, for all of your date/time, please add "Chart::chartTime(1000, 1, 1)"). This changes the date/time to all positive, and you can use setDateScale. In your custom formatting code, you can subtract the Chart::chartTime(1000, 1, 1) back to get the real value and format it accordingly.
Hope this can help.
Regards
Peter Kwan |
|