Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Feature/divvy #14

Merged
merged 4 commits into from

2 participants

@rbt
rbt commented

The user sets tick_division_type to one of the below module names (or their own module). This is loaded on the first call to divvy() and _real_divvy() is executed.

Divvy() was moved to Axis.pm from Data::Range.pm because it is a presentation side effect rather than something to do with the data itself. Producing a logarithmic display for the graph does not change the data which could be used in more than one location.

Exact is the old mechanism of dividing the space into equal tick segments.

exact

LinearRounded produces values which are (close to?) visually pleasing (nice whole figures) while keeping the number of ticks somewhere around what the user requested (default of 5).

linearrounded

LinearExpandGraph is an experimental mechanism taken from branch divvy_strategy. In my opinion LinearRounded produces better results but having multiple examples shows that the module loading functions correctly.

linearexpandgraph

Most importantly, users may create and use their own Divvy mechanism. Time based divvy logic will be somewhat different than the simple number set I have done; so I expect the number of Divvy modules to increase.

Implementing a Logarithmic divvy() from here is straight forward. The rest of the adjustments for logarithmic output isn't so obvious.

Rod Taylor added some commits
Rod Taylor Implement a more visually pleasing divvy()
The user sets tick_division_type to one of the below module names (or their own module). This is loaded on the first call to divvy() and _real_divvy() is executed.

Divvy() was moved to Axis.pm from Data::Range.pm because it is a presentation side effect rather than something to do with the data itself. Producing a logarithmic display for the graph does not change the data which could be used in more than one location.

LinearRounded produces values which are visually pleasing (nice whole figures) while keeping the number of ticks somewhere around what the user requested (default of 5).

Exact is the old mechanism of dividing the space into equal tick segments.

LinearExpandGraph is an experimental mechanism taken from branch divvy_strategy. In my opinion LinearRounded produces better results but having multiple examples shows that the module loading functions correctly.
7e64197
Rod Taylor Remove debug prints 4a07f75
Rod Taylor Do not adjust tick count. 50cddbe
@rbt
rbt commented

Included is the script I used to generate those images:

#!/usr/bin/env perl

use 5.14.2;

use Chart::Clicker;
use Chart::Clicker::Renderer::CandleStick;
use Chart::Clicker::Renderer::StackedBar;
use Chart::Clicker::Decoration::Legend::Tabular;
use Number::Format;

my $CHART_WIDTH       = '600';
my $MAIN_CHART_HEIGHT = '300';
my $SUB_CHART_HEIGHT  = '100';

#my $AXIS_DIVVY_TYPE = 'Exact';
#my $AXIS_DIVVY_TYPE = 'LinearRounded';
my $AXIS_DIVVY_TYPE = 'LinearExpandGraph';

# Necessary for alignment because the subgraph and main
# graph may have different widths
my $MINIMUM_AXIS_WIDTH = 75;

my %GRAPH_DATA = (
    price  => [ 28.20,  29,  29,  31.8,  30,  29,  27.50 ],     # Sample price data
    volume => [ 100, 200, 250, 300, 200, 100, 350 ],    # Sample volume data
    day_of_week => [ 1 .. 7 ],
);

my $cc = Chart::Clicker->new( format => 'png', width => $CHART_WIDTH, height => $MAIN_CHART_HEIGHT );
$cc->title->text('Price and Volume Chart');

# Add the volume subgraph
my $cvolumebar = Chart::Clicker->new( width => $CHART_WIDTH, height => $SUB_CHART_HEIGHT );
$cvolumebar->legend->visible(0);
$cc->add_subgraph($cvolumebar);

my $pricectx  = $cc->get_context('default');
my $volumectx = $cvolumebar->get_context('default');

my $priceSeries = Chart::Clicker::Data::Series->new(
    keys   => $GRAPH_DATA{'day_of_week'},
    values => $GRAPH_DATA{'price'},
    name   => 'Price'
);
my $priceDataSet = Chart::Clicker::Data::DataSet->new( series => [$priceSeries] );
$priceDataSet->context('default');
$cc->add_to_datasets($priceDataSet);

my $volumeSeries = Chart::Clicker::Data::Series->new(
    keys   => $GRAPH_DATA{'day_of_week'},
    values => $GRAPH_DATA{'volume'},
    name   => 'Volume',

);
my $volumeDataSet = Chart::Clicker::Data::DataSet->new(
    series => [$volumeSeries],
    lower  => 0
);
$volumeDataSet->context('default');
$cvolumebar->add_to_datasets($volumeDataSet);

$cc->plot->grid->visible(1);
$cvolumebar->plot->grid->visible(1);


$pricectx->range_axis->tick_division_type($AXIS_DIVVY_TYPE);
$pricectx->range_axis->label(q{Price});
$pricectx->range_axis->show_ticks(1);
$pricectx->range_axis->ticks(3);
$pricectx->range_axis->fudge_amount(0.01);
$pricectx->range_axis->minimum_width($MINIMUM_AXIS_WIDTH);

$pricectx->domain_axis->tick_division_type($AXIS_DIVVY_TYPE);
$volumectx->domain_axis->tick_division_type($AXIS_DIVVY_TYPE);
$pricectx->domain_axis->label('Day of Month');

$volumectx->range_axis->tick_division_type($AXIS_DIVVY_TYPE);
$volumectx->range_axis->label(q{Volume});
$volumectx->range_axis->ticks(2);
$volumectx->range_axis->minimum_width($MINIMUM_AXIS_WIDTH);

# Ensure the volume axis begins from 0. The default is to begin
# from the smallest volume given, which is 100 in this example
$volumectx->range_axis->range->lower(0);

# Keep vertical tick grid but skip the labels. 
$volumectx->domain_axis->show_ticks(1);
$volumectx->domain_axis->format( sub { return q{} });

# Render price as a line
$pricectx->renderer( Chart::Clicker::Renderer::Line->new() );

# Render volume as a bar
$volumectx->renderer( Chart::Clicker::Renderer::StackedBar->new() );

$cc->write_output(lc($AXIS_DIVVY_TYPE) .'.png');
Rod Taylor Correct handling of range->lower().
It was mistakenly cutting off the display of the bottom of the chart by adjusting to the lowest tick. The graph may be drawn below the lowest tick.
2d08adc
@gphat gphat merged commit 36aabb2 into gphat:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 2, 2013
  1. Implement a more visually pleasing divvy()

    Rod Taylor authored
    The user sets tick_division_type to one of the below module names (or their own module). This is loaded on the first call to divvy() and _real_divvy() is executed.
    
    Divvy() was moved to Axis.pm from Data::Range.pm because it is a presentation side effect rather than something to do with the data itself. Producing a logarithmic display for the graph does not change the data which could be used in more than one location.
    
    LinearRounded produces values which are visually pleasing (nice whole figures) while keeping the number of ticks somewhere around what the user requested (default of 5).
    
    Exact is the old mechanism of dividing the space into equal tick segments.
    
    LinearExpandGraph is an experimental mechanism taken from branch divvy_strategy. In my opinion LinearRounded produces better results but having multiple examples shows that the module loading functions correctly.
  2. Remove debug prints

    Rod Taylor authored
  3. Do not adjust tick count.

    Rod Taylor authored
  4. Correct handling of range->lower().

    Rod Taylor authored
    It was mistakenly cutting off the display of the bottom of the chart by adjusting to the lowest tick. The graph may be drawn below the lowest tick.
This page is out of date. Refresh to see the latest.
View
75 lib/Chart/Clicker/Axis.pm
@@ -1,13 +1,18 @@
package Chart::Clicker::Axis;
use Moose;
+use Moose::Util;
extends 'Chart::Clicker::Container';
with 'Chart::Clicker::Positioned';
# ABSTRACT: An X or Y Axis
+use Class::Load;
+
use Chart::Clicker::Data::Range;
+use English qw(-no_match_vars);
+
use Graphics::Color::RGB;
use Graphics::Primitive::Font;
@@ -49,10 +54,33 @@ The angle (in radians) to rotate the tick's labels.
=cut
has 'tick_label_angle' => (
- is => 'rw',
+ is => 'rw',
isa => 'Num'
);
+=attr tick_division_type
+
+Selects the algorithm for dividing the graph axis into labelled ticks.
+
+The currently included algorithms are:
+L<Chart::Clicker::Data::DivisionType::Exact/Exact>,
+L<Chart::Clicker::Data::DivisionType::RoundedLinear/RoundedLinear>.
+
+You may write your own by providing a Moose Role which includes Role
+L<Chart::Clicker::Data::DivisionType> and prefixing the module name
+with + when setting tick_division_type.
+
+ Chart::Clicker::Axis->new(tick_division_type => '+MyApp::TickDivision');
+
+This value should only be set once per axis.
+
+=cut
+
+has 'tick_division_type' => ( is => 'rw', isa => 'Str', default => 'Exact' );
+
+# The above tick division type is loaded on the first call to divvy()
+has '_tick_division_type_loaded' => ( is => 'ro', isa => 'Bool', lazy_build => 1 );
+
=attr baseline
The 'baseline' value of this axis. This is used by some renderers to change
@@ -349,6 +377,32 @@ sub BUILD {
$self->padding(3);
}
+sub _build__tick_division_type_loaded {
+ my $self = shift;
+
+ # User modules are prefixed with a +.
+ my $divisionTypeModule;
+ my $extensionOf = 'Chart::Clicker::Axis::DivisionType';
+ if ( $self->tick_division_type =~ m/^\+(.*)$/xmisg ) {
+ $divisionTypeModule = $1;
+ }
+ else {
+ $divisionTypeModule = sprintf( '%s::%s', $extensionOf, $self->tick_division_type );
+ }
+
+ # Try to load the DivisionType module. An error is thrown when the class is
+ # not available or cannot be loaded
+ Class::Load::load_class($divisionTypeModule);
+
+ # Apply the newly loaded role to this class.
+ Moose::Util::apply_all_roles( $self => $divisionTypeModule );
+ if ( not $self->does($extensionOf) ) {
+ die("Module $divisionTypeModule does not extend $extensionOf");
+ }
+
+ return 1;
+}
+
override('prepare', sub {
my ($self, $driver) = @_;
@@ -389,7 +443,7 @@ override('prepare', sub {
}
if($self->show_ticks && !scalar(@{ $self->tick_values })) {
- $self->tick_values($self->range->divvy($self->ticks + 1));
+ $self->tick_values($self->divvy);
}
# Return now without setting a min height or width and allow
@@ -707,8 +761,23 @@ sub format_value {
}
}
+=method divvy
+
+Retrieves the divisions or ticks for the axis.
+
+=cut
+
+sub divvy {
+ my $self = shift;
+
+ # Loads the divvy module once and only once
+ # which implements _real_divvy()
+ $self->_tick_division_type_loaded;
+ return $self->_real_divvy();
+}
+
__PACKAGE__->meta->make_immutable;
no Moose;
-1;
+1;
View
28 lib/Chart/Clicker/Axis/DivisionType.pm
@@ -0,0 +1,28 @@
+package Chart::Clicker::Axis::DivisionType;
+use Moose::Role;
+requires qw{range ticks};
+
+no Moose;
+
+1;
+__END__
+
+=head1 NAME
+
+Chart::Clicker::Axis::DivisionType - Division style for ticks
+
+=head1 DESCRIPTION
+
+
+=head1 AUTHOR
+
+Rod Taylor <chartclicker@rbt.ca>
+
+=head1 SEE ALSO
+
+perl(1)
+
+=head1 LICENSE
+
+You can redistribute and/or modify this code under the same terms as Perl
+itself.
View
67 lib/Chart/Clicker/Axis/DivisionType/Exact.pm
@@ -0,0 +1,67 @@
+package Chart::Clicker::Axis::DivisionType::Exact;
+
+use Moose::Role;
+with qw{Chart::Clicker::Axis::DivisionType};
+
+sub best_tick_size {
+ my ($self) = @_;
+
+ return $self->range->span / ( $self->ticks - 1 );
+}
+
+sub _real_divvy {
+ my ($self) = @_;
+
+ my $per = $self->best_tick_size;
+
+ my @vals;
+ for ( 0 .. ( $self->ticks - 1 ) ) {
+ push( @vals, $self->range->lower + ( $_ * $per ) );
+ }
+
+ return \@vals;
+}
+
+no Moose;
+1;
+__END__
+
+=head1 NAME
+
+Chart::Clicker::Axis::DivisionType::Exact - Divide axis in exact increments, linear scale.
+
+=head1 DESCRIPTION
+
+Role describing how to divide data for Chart::Clicker::Axis.
+
+=head1 SYNOPSIS
+
+ use Chart::Clicker::Axis;
+
+ my $axis = Chart::Clicker::Axis->new({
+ tick_division_type => 'Exact'
+ });
+
+=head1 METHODS
+
+=head2 best_tick_size
+
+The tick division calculated by taking the range and dividing by the requested number of ticks.
+
+=head2 divvy
+
+Divides the range up into exact division for L<Chart::Clicker::Axis>.
+
+=head1 AUTHOR
+
+Rod Taylor <chartclicker@rbt.ca>
+
+=head1 SEE ALSO
+
+perl(1)
+
+=head1 LICENSE
+
+You can redistribute and/or modify this code under the same terms as Perl
+itself.
+
View
136 lib/Chart/Clicker/Axis/DivisionType/LinearExpandGraph.pm
@@ -0,0 +1,136 @@
+package Chart::Clicker::Axis::DivisionType::LinearExpandGraph;
+
+use Moose::Role;
+with qw{Chart::Clicker::Axis::DivisionType};
+
+use POSIX qw(ceil floor);
+
+# Positive only
+has 'tick_slop' => (
+ is => 'rw',
+ isa => 'Num',
+ default => 0.1,
+ documentation =>
+ q{Percent of a tick unit above or below graphed which we allow inserting an additional tick. Whitespace allowance above or below.}
+);
+
+sub _real_divvy {
+ my ($self) = @_;
+
+ my $n = $self->ticks;
+
+ my $min = $self->range->lower;
+ my $max = $self->range->upper;
+
+ my $range = _nicenum($self->range->span, 0);
+ my $d = _nicenum($range / ($n - 1), 1);
+ my $graphmin = $min;
+ my $graphmax = $max;
+
+ # Expand the graph as needed
+ $graphmin = floor($min / $d) * $d;
+ $self->range->min($graphmin);
+ $graphmax = ceil($max / $d) * $d;
+ $self->range->max($graphmax);
+
+ my $x = $graphmin;
+ my @ticks;
+ do {
+ push(@ticks, $x);
+ $x += .5 * $d;
+ } while($x < $graphmax);
+
+ return \@ticks;
+}
+
+sub _nicenum {
+ my ($num, $round) = @_;
+
+ my $exp = floor(_log10($num));
+ my $f = $num / (10 ** $exp);
+ my $nice;
+
+ if($round) {
+ if($f < 1.5) {
+ $nice = 1.5;
+ } elsif($f < 3) {
+ $nice = 2;
+ } elsif($f < 7) {
+ $nice = 5;
+ } else {
+ $nice = 10;
+ }
+ } else {
+ if($f <= 1) {
+ $nice = 1;
+ } elsif($f <= 2) {
+ $nice = 2;
+ } elsif($f <= 5) {
+ $nice = 5;
+ } else {
+ $nice = 10;
+ }
+ }
+
+ return $nice * (10 ** $exp);
+}
+
+
+
+sub _log10 {
+ my $n = shift;
+ return log($n) / log(10);
+}
+
+no Moose;
+1;
+__END__
+
+=head1 NAME
+
+Chart::Clicker::Axis::DivisionType::RoundedLinear - Nicely rounded segments on a linear scale.
+
+=head1 DESCRIPTION
+
+Role describing how to divide data for Chart::Clicker::Axis.
+
+=head1 SYNOPSIS
+
+ use Chart::Clicker::Axis;
+
+ my $axis = Chart::Clicker::Axis->new({
+ tick_division_type => 'RoundedLinear'
+ });
+
+=head1 ATTRIBUTES
+
+=head2 tick_slop
+
+This setting determines whether to add a tick outside of the data. If the tick would be
+within the percentage of a ticks size specified here as a decimal (10% would be 0.1), then
+the tick will be added expanding the graph.
+
+=head1 METHODS
+
+=head2 best_tick_size
+
+The tick division considered best for the approximate number of ticks requested
+and data within the range.
+
+=head2 divvy
+
+Divides the range up into nicely rounded chunks for L<Chart::Clicker::Axis>.
+
+=head1 AUTHOR
+
+Rod Taylor <chartclicker@rbt.ca>
+
+=head1 SEE ALSO
+
+perl(1)
+
+=head1 LICENSE
+
+You can redistribute and/or modify this code under the same terms as Perl
+itself.
+
View
149 lib/Chart/Clicker/Axis/DivisionType/LinearRounded.pm
@@ -0,0 +1,149 @@
+package Chart::Clicker::Axis::DivisionType::LinearRounded;
+
+use Moose::Role;
+with qw{Chart::Clicker::Axis::DivisionType};
+
+# Positive only
+has 'tick_slop' => (
+ is => 'rw',
+ isa => 'Num',
+ default => 0.1,
+ documentation =>
+ q{Percent of a tick unit above or below graphed which we allow inserting an additional tick. Whitespace allowance above or below.}
+);
+
+# Take the rough tick size which is the smallest possible 'round' scale
+# and use other sub-divisors to aim for the number of ticks specified.
+sub best_tick_size {
+ my ($self) = @_;
+
+ my $minimum_target_ticks = $self->ticks;
+ $minimum_target_ticks = 1 if ( $minimum_target_ticks < 1 );
+
+ my $equal_tick_size = $self->range->span / ($minimum_target_ticks);
+
+ # Provide a nice round divisor which is within an order of
+ # magnitude of the actual wanted tick size. We adjust
+ # this value using hand specified sub-divider values
+ #
+ # Small ranges (below 1) require an additional digit
+ my $digits = int( log( abs($equal_tick_size) ) / log(10) );
+ $digits-- if ( abs( $self->range->span ) < 1 );
+ my $scale_size = 10**$digits;
+
+ # Take the largest divider (smallest number of ticks) which will provide
+ # a nice looking result. The below dividers were selected arbitrarily to
+ # create visually pleasing numbers for an axis.
+ #
+ # The number of ticks will be equal to or larger than the requested number
+ # of ticks. Never smaller. The worst case is the 1 to 2 range which may
+ # provide nearly double (2N - 1) the number of requested ticks.
+ADJUSTSCALE:
+ for my $scale_divider ( 25, 20, 10, 5, 4, 2.5, 2, 1 ) {
+ my $test_scale = $scale_divider * $scale_size;
+
+ if ( $self->range->span / $test_scale >= $minimum_target_ticks ) {
+ $scale_size = $test_scale;
+ last ADJUSTSCALE;
+ }
+ }
+
+ return $scale_size;
+}
+
+sub _real_divvy {
+ my ($self) = @_;
+
+ my $tickSize = $self->best_tick_size;
+ my $range = $self->range;
+
+ # If the lowest value is nearby to the first tick below it (gap
+ # at front of graph would be low) then use that as the starting
+ # value; otherwise choose the first tick value above the lowest.
+ my $lowestTick = int( $range->lower() / $tickSize ) * $tickSize;
+ my $lowestValue = $range->lower();
+ my $lowTickDifference = $lowestValue - $lowestTick;
+
+ if ( $lowTickDifference > $self->tick_slop * $tickSize ) {
+ $lowestTick = $lowestTick + $tickSize;
+ }
+ if ( $lowestTick < $lowestValue ) {
+ $lowestValue = $lowestTick;
+ }
+ $range->lower($lowestValue);
+ my @vals;
+ push( @vals, $lowestTick );
+
+ # Loop until upper from the starting point
+ my $lastTick = $lowestTick;
+ while ( $range->upper - $tickSize > $lastTick ) {
+ $lastTick = $lastTick + $tickSize;
+
+ push( @vals, $lastTick );
+ }
+
+ # If the upper value is nearby to the last tick above it
+ # (gap at end of graph would be low) then use that as the
+ # ending value; otherwise use the tick value immediately before
+ # the upper value.
+ my $potentialUpperTick = $lastTick + $tickSize;
+ if ( $potentialUpperTick - $range->upper < $self->tick_slop * $tickSize ) {
+ $range->upper($potentialUpperTick);
+ push( @vals, $potentialUpperTick );
+ }
+
+ return \@vals;
+}
+
+no Moose;
+1;
+__END__
+
+=head1 NAME
+
+Chart::Clicker::Axis::DivisionType::RoundedLinear - Nicely rounded segments on a linear scale.
+
+=head1 DESCRIPTION
+
+Role describing how to divide data for Chart::Clicker::Axis.
+
+=head1 SYNOPSIS
+
+ use Chart::Clicker::Axis;
+
+ my $axis = Chart::Clicker::Axis->new({
+ tick_division_type => 'RoundedLinear'
+ });
+
+=head1 ATTRIBUTES
+
+=head2 tick_slop
+
+This setting determines whether to add a tick outside of the data. If the tick would be
+within the percentage of a ticks size specified here as a decimal (10% would be 0.1), then
+the tick will be added expanding the graph.
+
+=head1 METHODS
+
+=head2 best_tick_size
+
+The tick division considered best for the approximate number of ticks requested
+and data within the range.
+
+=head2 divvy
+
+Divides the range up into nicely rounded chunks for L<Chart::Clicker::Axis>.
+
+=head1 AUTHOR
+
+Rod Taylor <chartclicker@rbt.ca>
+
+=head1 SEE ALSO
+
+perl(1)
+
+=head1 LICENSE
+
+You can redistribute and/or modify this code under the same terms as Perl
+itself.
+
View
35 lib/Chart/Clicker/Data/Range.pm
@@ -50,6 +50,15 @@ Set/Get the upper bound for this Range
has 'upper' => ( is => 'rw', isa => 'Num' );
+=attr ticks
+
+The number of ticks to be displayed for this range.
+
+=cut
+
+has 'ticks' => ( is => 'rw', isa => 'Int', default => 5 );
+
+
after 'lower' => sub {
my $self = shift;
@@ -143,32 +152,6 @@ sub contains {
return 0;
}
-=method divvy
-
- my $values = $range->divvy(5);
-
-Returns an arrayref of $N - 1 values equally spaced in the range so that
-it may be divided into $N pieces.
-
-=cut
-
-sub divvy {
- my ($self, $n) = @_;
-
- if(!$n) {
- return [];
- }
-
- my $per = $self->span / ($n - 1);
-
- my @vals;
- for(0..($n - 1)) {
- push(@vals, $self->lower + ($_ * $per));
- }
-
- return \@vals;
-}
-
=method span
Returns the span of this range, or UPPER - LOWER.
View
84 t/axis-division-rounded.t
@@ -0,0 +1,84 @@
+use Test::More;
+
+BEGIN {
+ use_ok('Chart::Clicker::Axis');
+}
+my $label = 'Foo';
+
+# Small Range
+{
+ my $axis = Chart::Clicker::Axis->new(
+ label => $label,
+ orientation => 'vertical',
+ position => 'left',
+ tick_division_type => 'LinearRounded'
+ );
+
+ ok( defined( $axis->range() ), 'Has range' );
+
+ $axis->range->lower(3);
+ $axis->range->upper(105);
+ is( $axis->ticks, '5', 'Default number of ticks' );
+ is_deeply( $axis->divvy(), [ 25, 50, 75, 100 ], 'Nicely rounded tick values - medium scale' );
+}
+
+# Larger Range
+{
+ my $axis = Chart::Clicker::Axis->new(
+ label => $label,
+ orientation => 'vertical',
+ position => 'left',
+ tick_division_type => 'LinearRounded'
+ );
+ $axis->range->lower(1);
+ $axis->range->upper(999123421);
+ is_deeply(
+ $axis->divvy(),
+ [ 0, 200000000, 400000000, 600000000, 800000000, 1000000000 ],
+ 'Nicely rounded tick values - large scale 5 ticks'
+ );
+}
+
+# Large range, small tick count
+{
+ my $axis = Chart::Clicker::Axis->new(
+ label => $label,
+ orientation => 'vertical',
+ position => 'left',
+ tick_division_type => 'LinearRounded'
+ );
+ $axis->range->lower(1);
+ $axis->range->upper(999123421);
+ $axis->ticks(3);
+ is_deeply( $axis->divvy(), [ 0, 400000000, 800000000 ], 'Nicely rounded tick values - large scale 3 ticks' );
+}
+
+# Very small range below 1
+{
+ my $axis = Chart::Clicker::Axis->new(
+ label => $label,
+ orientation => 'vertical',
+ position => 'left',
+ tick_division_type => 'LinearRounded'
+ );
+ $axis->range->lower(0.0072);
+ $axis->range->upper(0.0078);
+ $axis->ticks(3);
+ is_deeply( $axis->divvy(), [ 0.00725, 0.00750, 0.00775 ], 'Nicely rounded tick values - large scale 3 ticks' );
+}
+
+# Very small range above 1
+{
+ my $axis = Chart::Clicker::Axis->new(
+ label => $label,
+ orientation => 'vertical',
+ position => 'left',
+ tick_division_type => 'LinearRounded'
+ );
+ $axis->range->lower(1.5672);
+ $axis->range->upper(1.5679);
+ $axis->ticks(4);
+ is_deeply( $axis->divvy(), [ 1.5672, 1.5674, 1.5676, 1.5678 ], 'Nicely rounded tick values - large scale 3 ticks' );
+}
+
+done_testing;
View
1  t/axis.t
@@ -5,6 +5,7 @@ BEGIN {
}
my $label = 'Foo';
+# Exact tick_division_type by default
my $axis = Chart::Clicker::Axis->new(
label => $label, orientation => 'vertical', position => 'left'
);
View
3  t/data-range.t
@@ -8,9 +8,6 @@ isa_ok($range, 'Chart::Clicker::Data::Range', 'isa Chart::Clicker::Data::Range')
cmp_ok($range->lower, '==', 0, 'Lower');
cmp_ok($range->upper, '==', 10, 'Upper');
-my $divvy = $range->divvy(5);
-cmp_ok(scalar(@{ $divvy }), '==', 5, 'divvy count');
-is_deeply($divvy, [ 0, 2.5, 5, 7.5, 10 ], 'divvy results');
cmp_ok($range->span, '==', 10, 'span');
ok($range->contains(0), 'range contains 0');
ok($range->contains(5), 'range contains 5');
Something went wrong with that request. Please try again.