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.