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.
                 

Reply via email to