Bug#359943: libchart-perl: integer_ticks_only doesn't honor max_y_ticks

Niko Tyni ntyni at iki.fi
Sun Apr 9 12:20:05 UTC 2006


On Tue, Apr 04, 2006 at 11:58:32AM +0200, Bill Allombert wrote:

> Unfortunately there is a bug: 
> 
> The larger tick value is smaller than the max, or it is drawn outside
> the chart.

Thanks, so there is. I'm attaching a new try at a patch.  It also uses
m*10^n as the interval, where m is 1,2 or 5, to mimic the behaviour
without 'integer_ticks_only'.

The previous patch didn't apply because Chart/Base.pm uses DOS-style
newlines, and they had got lost somewhere on the way. This one should
apply cleanly against 2.4.1-3.

Please tell me if it works for you.

Cheers,
-- 
Niko Tyni	ntyni at iki.fi
-------------- next part --------------
--- Chart/Base.pm.orig	2006-04-09 14:47:02.268171711 +0300
+++ Chart/Base.pm	2006-04-09 14:58:26.590677648 +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,44 @@
 	    $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);
 
             # Now sort out an array of tick labels.
                 


More information about the pkg-perl-maintainers mailing list