On Tue, Apr 11, 2006 at 10:01:56PM +0200, Bill Allombert wrote:
> 1) The lower bound should be probably rounded down to the next multiple
> of the interval. This is the behaviour when integer_ticks_only is off.
Right. One more round of iteration attached.
> 2) the patch did not apply so I used fromdos on Base.pm and it applied.
> Maybe my MUA has converted the patch to UNIX lines.
No, the problem is at my end. I hope this one comes through correctly.
(I'm using 'application/x-patch' instead of 'text/plain' now.)
> 3) I would suggest the default for max_y_ticks to be the same with or
> without integer_ticks_only (the manpage suggests so). A specific value
> could be used for max_y_ticks to denote the correct behaviour (no max).
I don't understand this.
The default for max_y_ticks is the same in both cases, 100. The
'integer_ticks_only' code aims for a tick interval of 1, but if that goes
over max_y_ticks, it starts compensating. Without 'integer_ticks_only',
the 'max_y_ticks' kicks in only with non-integer tick intervals.
I don't understand the sentence about "a specific value for the correct
behaviour" either. Could you clarify, please?
Cheers,
--
Niko Tyni [EMAIL PROTECTED]
--- Chart/Base.pm.orig 2006-04-09 14:47:02.000000000 +0300
+++ Chart/Base.pm 2006-04-16 18:47:48.000000000 +0300
@@ -41,6 +41,7 @@
use strict;
use Carp;
use FileHandle;
+use POSIX qw(ceil);
$Chart::Base::VERSION = '2.4.1';
@@ -1815,6 +1816,40 @@
return 1;
}
+# calculate an integer tick interval, given a range and the number of ticks
+# round up- or downwards to 1,2 or 5 * 10^n
+
+sub _recalc_integer_tickinterval {
+ my $self = shift;
+
+ my ($range, $ticks, $round) = @_;
+ die("a range of 0 makes no sense") if ($range == 0);
+
+ my $tickInterval = $range / ($ticks - 1);
+ my ($exponent, $mantissa) = $self->_sepFP($tickInterval);
+ die("an interval 0 makes no sense") if ($mantissa == 0);
+
+ while ($mantissa < 1) {
+ $mantissa *= 10;
+ $exponent--;
+ }
+ if ($exponent < 0) { # minimum interval is 1
+ $exponent = 0;
+ $mantissa = 1;
+ } elsif ($round > 0) { # round upwards
+ for (2,5,10) {
+ $mantissa = $_, last if $mantissa < $_;
+ }
+ } else { # round downwards
+ for (5,2,1) {
+ $mantissa = $_, last if $mantissa > $_;
+ }
+ }
+ $tickInterval = $mantissa * 10 ** $exponent;
+
+ my $newTickCount = ceil($range / $tickInterval) + 1;
+ return ($tickInterval, $newTickCount);
+}
## find good values for the minimum and maximum y-value on the chart
# New version, re-written by David Pottage of Tao Group.
@@ -1911,6 +1946,51 @@
$tickInterval = $skip;
$tickCount = ($p_max - $p_min ) / $skip + 1;
+ # Honor max_y_ticks, even if that means overriding skip_int_ticks.
+ if ($tickCount > $self->{'max_y_ticks'}) {
+ ($tickInterval, $tickCount)
+ = $self->_recalc_integer_tickinterval(
+ $p_max - $p_min, $self->{'max_y_ticks'}, 1);
+ }
+
+ # Honor min_y_ticks if we can, first by reducing tick interval
+ # (even if that means overriding skip_int_ticks)
+ # and then by increasing the range if allowed.
+ if ($tickCount < $self->{'min_y_ticks'}) {
+ ($tickInterval, $tickCount)
+ = $self->_recalc_integer_tickinterval(
+ $p_max - $p_min, $self->{'min_y_ticks'}, -1);
+
+ if ($tickCount < $self->{'min_y_ticks'} &&
+ (!$f_max || !$f_min)) {
+ # Reducing interval didn't work, we have to increase the range.
+ # Just don't do it if both min_val and max_val were specified.
+
+ my $minRange = $tickInterval * ($self->{'min_y_ticks'} - 1);
+ if (!$f_max) {
+ $d_max = $d_min + $minRange;
+ $p_max = $self->_round2Tick($d_max, 1, 1);
+ } elsif (!$f_min) {
+ $d_min = $d_max - $minRange;
+ $p_min = $self->_round2Tick($d_min, 1, -1);
+ }
+
+ # recalculate the tick interval once more
+ ($tickInterval, $tickCount)
+ = $self->_recalc_integer_tickinterval(
+ $p_max - $p_min, $self->{'min_y_ticks'}, -1);
+ }
+ }
+
+ # set $p_max to the real maximum value of the graph
+ $p_max = $p_min + $tickInterval * ($tickCount - 1);
+
+ # round the minimum value down to the nearest multiple of the
+ # interval
+
+ if ($p_min % $tickInterval != 0 && !$f_min) {
+ $p_min -= ($p_min % $tickInterval);
+ }
# Now sort out an array of tick labels.