File Coverage

blib/lib/Chart/Bars.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             ## @file
2             # Implementation of Chart::Bars
3             #
4             # written by
5             # @author david bonner (dbonner@cs.bu.edu)
6             #
7             # maintained by the
8             # @author Chart Group at Geodetic Fundamental Station Wettzell (Chart@fs.wettzell.de)
9             # @date 2012-10-03
10             # @version 2.4.6
11              
12             ## @class Chart::Bars
13             # Bars class provides all functions which are specific to
14             # vertical bars
15             package Chart::Bars;
16              
17 11     11   24360 use Chart::Base '2.4.6';
  0            
  0            
18             use GD;
19             use Carp;
20              
21             use strict;
22              
23             @Chart::Bars::ISA = qw(Chart::Base);
24             $Chart::Bars::VERSION = '2.4.6';
25              
26             #>>>>>>>>>>>>>>>>>>>>>>>>>>#
27             # public methods go here #
28             #<<<<<<<<<<<<<<<<<<<<<<<<<<#
29              
30             #>>>>>>>>>>>>>>>>>>>>>>>>>>>#
31             # private methods go here #
32             #<<<<<<<<<<<<<<<<<<<<<<<<<<<#
33              
34             ## @method private _draw_data
35             # finally get around to plotting the data for (vertical) bars
36             #
37             sub _draw_data
38             {
39             my $self = shift;
40              
41             my $data = $self->{'dataref'};
42             my $misccolor = $self->_color_role_to_index('misc');
43             my ( $x1, $x2, $x3, $y1, $y2, $y3 );
44             my ( $width, $height, $delta1, $delta2, $map, $mod, $cut, $pink );
45             my ( $i, $j, $color );
46             my $temp = 0;
47              
48             # init the imagemap data field if they wanted it
49             if ( $self->true( $self->{'imagemap'} ) )
50             {
51             $self->{'imagemap_data'} = [];
52             }
53              
54             # find both delta values ($delta1 for stepping between different
55             # datapoint names, $delta2 for stepping between datasets for that
56             # point) and the mapping constant
57             $width = $self->{'curr_x_max'} - $self->{'curr_x_min'};
58             $height = $self->{'curr_y_max'} - $self->{'curr_y_min'};
59             $delta1 =
60             ( $self->{'num_datapoints'} > 0 )
61             ? $width / ( $self->{'num_datapoints'} * 1 )
62             : $width;
63              
64             $map =
65             ( ( $self->{'max_val'} - $self->{'min_val'} ) > 0 )
66             ? $height / ( $self->{'max_val'} - $self->{'min_val'} )
67             : $height;
68              
69             if ( $self->true( $self->{'spaced_bars'} ) )
70             {
71              
72             #OLD: $delta2 = $delta1 / ($self->{'num_datasets'} + 2);
73             $delta2 =
74             ( ( $self->{'num_datasets'} + 2 ) > 0 )
75             ? $delta1 / ( $self->{'num_datasets'} + 2 )
76             : $delta1;
77             }
78             else
79             {
80             $delta2 =
81             ( $self->{'num_datasets'} > 0 )
82             ? $delta1 / $self->{'num_datasets'}
83             : $delta1;
84             }
85              
86             # get the base x-y values
87             $x1 = $self->{'curr_x_min'};
88              
89             if ( $self->{'min_val'} >= 0 )
90             {
91             $y1 = $self->{'curr_y_max'};
92             $mod = $self->{'min_val'};
93             }
94             elsif ( $self->{'max_val'} <= 0 )
95             {
96             $y1 = $self->{'curr_y_min'};
97             $mod = $self->{'max_val'};
98             }
99             else
100             {
101             $y1 = $self->{'curr_y_min'} + ( $map * $self->{'max_val'} );
102             $mod = 0;
103             $self->{'gd_obj'}->line( $self->{'curr_x_min'}, $y1, $self->{'curr_x_max'}, $y1, $misccolor );
104             }
105              
106             # draw the bars
107             for $i ( 1 .. $self->{'num_datasets'} )
108             {
109              
110             # get the color for this dataset
111             $color = $self->_color_role_to_index( 'dataset' . ( $i - 1 ) );
112              
113             # draw every bar for this dataset
114             for $j ( 0 .. $self->{'num_datapoints'} )
115             {
116              
117             # don't try to draw anything if there's no data
118             if ( defined( $data->[$i][$j] )
119             && $data->[$i][$j] =~ /^[\-\+]{0,1}\s*[\d\.eE\-\+]+/ )
120             {
121              
122             # find the bounds of the rectangle
123             if ( $self->true( $self->{'spaced_bars'} ) )
124             {
125             $x2 = ( $x1 + ( $j * $delta1 ) + ( $i * $delta2 ) );
126             }
127             else
128             {
129             $x2 = $x1 + ( $j * $delta1 ) + ( ( $i - 1 ) * $delta2 );
130             }
131             $y2 = $y1;
132             $x3 = $x2 + $delta2;
133             $y3 = $y1 - ( ( $data->[$i][$j] - $mod ) * $map );
134              
135             # cut the bars off, if needed
136             if ( $data->[$i][$j] > $self->{'max_val'} )
137             {
138             $y3 = $y1 - ( ( $self->{'max_val'} - $mod ) * $map );
139             $cut = 1;
140             }
141             elsif ( $data->[$i][$j] < $self->{'min_val'} )
142             {
143             $y3 = $y1 - ( ( $self->{'min_val'} - $mod ) * $map );
144             $cut = 1;
145             }
146             else
147             {
148             $cut = 0;
149             }
150              
151             # draw the bar
152             ## y2 and y3 are reversed in some cases because GD's fill
153             ## algorithm is lame
154             if ( $data->[$i][$j] > 0 )
155             {
156             $self->{'gd_obj'}->filledRectangle( $x2, $y3, $x3, $y2, $color );
157             if ( $self->true( $self->{'imagemap'} ) )
158             {
159             $self->{'imagemap_data'}->[$i][$j] = [ $x2, $y3, $x3, $y2 ];
160             }
161             }
162             else
163             {
164             $self->{'gd_obj'}->filledRectangle( $x2, $y2, $x3, $y3, $color );
165             if ( $self->true( $self->{'imagemap'} ) )
166             {
167             $self->{'imagemap_data'}->[$i][$j] = [ $x2, $y2, $x3, $y3 ];
168             }
169             }
170              
171             # now outline it. outline red if the bar had been cut off
172             unless ($cut)
173             {
174             $self->{'gd_obj'}->rectangle( $x2, $y3, $x3, $y2, $misccolor );
175             }
176             else
177             {
178             $pink = $self->{'gd_obj'}->colorAllocate( 255, 0, 255 );
179             $self->{'gd_obj'}->rectangle( $x2, $y3, $x3, $y2, $pink );
180             }
181              
182             }
183             else
184             {
185             if ( $self->true( $self->{'imagemap'} ) )
186             {
187             $self->{'imagemap_data'}->[$i][$j] = [ undef(), undef(), undef(), undef() ];
188             }
189             }
190             }
191             }
192              
193             # and finaly box it off
194             $self->{'gd_obj'}
195             ->rectangle( $self->{'curr_x_min'}, $self->{'curr_y_min'}, $self->{'curr_x_max'}, $self->{'curr_y_max'}, $misccolor );
196             return;
197              
198             }
199              
200             ## be a good module and return 1
201             1;