line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
## @file |
2
|
|
|
|
|
|
|
# Implementation of Chart::HorizontalBars |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# maintained and written by the |
5
|
|
|
|
|
|
|
# @author Chart Group at Geodetic Fundamental Station Wettzell (Chart@fs.wettzell.de) |
6
|
|
|
|
|
|
|
# @date 2015-03-01 |
7
|
|
|
|
|
|
|
# @version 2.4.10 |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
## @class Chart::HorizontalBars |
10
|
|
|
|
|
|
|
# HorizontalBars class derived from class Base. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# This class provides all functions which are specific to |
13
|
|
|
|
|
|
|
# horizontal bars |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
package Chart::HorizontalBars; |
16
|
|
|
|
|
|
|
|
17
|
4
|
|
|
4
|
|
6772
|
use Chart::Base '2.4.10'; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
use GD; |
19
|
|
|
|
|
|
|
use Carp; |
20
|
|
|
|
|
|
|
use strict; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
@Chart::HorizontalBars::ISA = qw(Chart::Base); |
23
|
|
|
|
|
|
|
$Chart::HorizontalBars::VERSION = '2.4.10'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#>>>>>>>>>>>>>>>>>>>>>>>>>># |
26
|
|
|
|
|
|
|
# public methods go here # |
27
|
|
|
|
|
|
|
#<<<<<<<<<<<<<<<<<<<<<<<<<<# |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#>>>>>>>>>>>>>>>>>>>>>>>>>>># |
30
|
|
|
|
|
|
|
# private methods go here # |
31
|
|
|
|
|
|
|
#<<<<<<<<<<<<<<<<<<<<<<<<<<<# |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
## @method private int _draw_x_ticks() |
34
|
|
|
|
|
|
|
# draw the x-ticks and their labels |
35
|
|
|
|
|
|
|
# Overwrites this function of Chart::Base |
36
|
|
|
|
|
|
|
# @return status |
37
|
|
|
|
|
|
|
# |
38
|
|
|
|
|
|
|
sub _draw_x_ticks |
39
|
|
|
|
|
|
|
{ |
40
|
|
|
|
|
|
|
my $self = shift; |
41
|
|
|
|
|
|
|
my $data = $self->{'dataref'}; |
42
|
|
|
|
|
|
|
my $font = $self->{'tick_label_font'}; |
43
|
|
|
|
|
|
|
my $textcolor = $self->_color_role_to_index('text'); |
44
|
|
|
|
|
|
|
my $misccolor = $self->_color_role_to_index('misc'); |
45
|
|
|
|
|
|
|
my ( $h, $w, $x1, $y1, $y2, $x2, $delta, $width, $label ); |
46
|
|
|
|
|
|
|
my @labels = @{ $self->{'y_tick_labels'} }; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
$self->{'grid_data'}->{'x'} = []; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
#make sure we have a real font |
51
|
|
|
|
|
|
|
unless ( ( ref $font ) eq 'GD::Font' ) |
52
|
|
|
|
|
|
|
{ |
53
|
|
|
|
|
|
|
croak "The tick label font you specified isn't a GD font object"; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
#get height and width of the font |
57
|
|
|
|
|
|
|
( $h, $w ) = ( $font->height, $font->width ); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#get the right x-value and width |
60
|
|
|
|
|
|
|
if ( $self->{'y_axes'} =~ /^right$/i ) |
61
|
|
|
|
|
|
|
{ |
62
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
63
|
|
|
|
|
|
|
$width = |
64
|
|
|
|
|
|
|
$self->{'curr_x_max'} - $x1 - $self->{'tick_len'} - $self->{'text_space'} - $w * $self->{'x_tick_label_length'}; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
elsif ( $self->{'y_axes'} =~ /^both$/i ) |
67
|
|
|
|
|
|
|
{ |
68
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'} + $self->{'text_space'} + $w * $self->{'x_tick_label_length'} + $self->{'tick_len'}; |
69
|
|
|
|
|
|
|
$width = |
70
|
|
|
|
|
|
|
$self->{'curr_x_max'} - $x1 - $self->{'tick_len'} - $self->{'text_space'} - $w * $self->{'x_tick_label_length'}; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
else |
73
|
|
|
|
|
|
|
{ |
74
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'} + $self->{'text_space'} + $w * $self->{'x_tick_label_length'} + $self->{'tick_len'}; |
75
|
|
|
|
|
|
|
$width = $self->{'curr_x_max'} - $x1; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
#get the delta value |
79
|
|
|
|
|
|
|
$delta = $width / ( $self->{'y_ticks'} - 1 ); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#draw the labels |
82
|
|
|
|
|
|
|
$y2 = $y1; |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
if ( $self->{'x_ticks'} =~ /^normal/i ) |
85
|
|
|
|
|
|
|
{ #just normal ticks |
86
|
|
|
|
|
|
|
#get the point for updating later |
87
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - 2 * $self->{'text_space'} - $h - $self->{'tick_len'}; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
#get the start point |
90
|
|
|
|
|
|
|
$y2 = $y1 + $self->{'tick_len'} + $self->{'text_space'}; |
91
|
|
|
|
|
|
|
for ( 0 .. $#labels ) |
92
|
|
|
|
|
|
|
{ |
93
|
|
|
|
|
|
|
$label = $self->{'y_tick_labels'}[$_]; |
94
|
|
|
|
|
|
|
$x2 = $x1 + ( $delta * $_ ) - ( $w * length($label) / 2 ); |
95
|
|
|
|
|
|
|
$self->{'gd_obj'}->string( $font, $x2, $y2, $label, $textcolor ); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
elsif ( $self->{'x_ticks'} =~ /^staggered/i ) |
99
|
|
|
|
|
|
|
{ #staggered ticks |
100
|
|
|
|
|
|
|
#get the point for updating later |
101
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - 3 * $self->{'text_space'} - 2 * $h - $self->{'tick_len'}; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
for ( 0 .. $#labels ) |
104
|
|
|
|
|
|
|
{ |
105
|
|
|
|
|
|
|
$label = $self->{'y_tick_labels'}[$_]; |
106
|
|
|
|
|
|
|
$x2 = $x1 + ( $delta * $_ ) - ( $w * length($label) / 2 ); |
107
|
|
|
|
|
|
|
unless ( $_ % 2 ) |
108
|
|
|
|
|
|
|
{ |
109
|
|
|
|
|
|
|
$y2 = $y1 + $self->{'text_space'} + $self->{'tick_len'}; |
110
|
|
|
|
|
|
|
$self->{'gd_obj'}->string( $font, $x2, $y2, $label, $textcolor ); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
else |
113
|
|
|
|
|
|
|
{ |
114
|
|
|
|
|
|
|
$y2 = $y1 + $h + 2 * $self->{'text_space'} + $self->{'tick_len'}; |
115
|
|
|
|
|
|
|
$self->{'gd_obj'}->string( $font, $x2, $y2, $label, $textcolor ); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
elsif ( $self->{'x_ticks'} =~ /^vertical/i ) |
122
|
|
|
|
|
|
|
{ #vertical ticks |
123
|
|
|
|
|
|
|
#get the point for updating later |
124
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - 2 * $self->{'text_space'} - $w * $self->{'y_tick_label_length'} - $self->{'tick_len'}; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
for ( 0 .. $#labels ) |
127
|
|
|
|
|
|
|
{ |
128
|
|
|
|
|
|
|
$label = $self->{'y_tick_labels'}[$_]; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
#get the start point |
131
|
|
|
|
|
|
|
$y2 = $y1 + $self->{'tick_len'} + $w * length($label) + $self->{'text_space'}; |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
$x2 = $x1 + ( $delta * $_ ) - ( $h / 2 ); |
134
|
|
|
|
|
|
|
$self->{'gd_obj'}->stringUp( $font, $x2, $y2, $label, $textcolor ); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
else |
140
|
|
|
|
|
|
|
{ |
141
|
|
|
|
|
|
|
carp "I don't understand the type of x-ticks you specified"; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
#update the curr x and y max value |
145
|
|
|
|
|
|
|
$self->{'curr_y_max'} = $y1; |
146
|
|
|
|
|
|
|
$self->{'curr_x_max'} = $x1 + $width; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
#draw the ticks |
149
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'}; |
150
|
|
|
|
|
|
|
$y2 = $self->{'curr_y_max'} + $self->{'tick_len'}; |
151
|
|
|
|
|
|
|
for ( 0 .. $#labels ) |
152
|
|
|
|
|
|
|
{ |
153
|
|
|
|
|
|
|
$x2 = $x1 + ( $delta * $_ ); |
154
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x2, $y1, $x2, $y2, $misccolor ); |
155
|
|
|
|
|
|
|
if ( $self->true( $self->{'grid_lines'} ) |
156
|
|
|
|
|
|
|
or $self->true( $self->{'x_grid_lines'} ) ) |
157
|
|
|
|
|
|
|
{ |
158
|
|
|
|
|
|
|
$self->{'grid_data'}->{'x'}->[$_] = $x2; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
return 1; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
## @fn private int _draw_y_ticks() |
166
|
|
|
|
|
|
|
# draw the y-ticks and their labels |
167
|
|
|
|
|
|
|
# Overwrites this function of Chart::Base |
168
|
|
|
|
|
|
|
# @return status |
169
|
|
|
|
|
|
|
sub _draw_y_ticks |
170
|
|
|
|
|
|
|
{ |
171
|
|
|
|
|
|
|
my $self = shift; |
172
|
|
|
|
|
|
|
my $side = shift || 'left'; |
173
|
|
|
|
|
|
|
my $data = $self->{'dataref'}; |
174
|
|
|
|
|
|
|
my $font = $self->{'tick_label_font'}; |
175
|
|
|
|
|
|
|
my $textcolor = $self->_color_role_to_index('text'); |
176
|
|
|
|
|
|
|
my $misccolor = $self->_color_role_to_index('misc'); |
177
|
|
|
|
|
|
|
my ( $h, $w, $x1, $x2, $y1, $y2 ); |
178
|
|
|
|
|
|
|
my ( $width, $height, $delta ); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
$self->{'grid_data'}->{'y'} = []; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
#make sure that is a real font |
183
|
|
|
|
|
|
|
unless ( ( ref $font ) eq 'GD::Font' ) |
184
|
|
|
|
|
|
|
{ |
185
|
|
|
|
|
|
|
croak "The tick label font isn't a GD Font object!"; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
#get the size of the font |
189
|
|
|
|
|
|
|
( $h, $w ) = ( $font->height, $font->width ); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
#figure out, where to draw |
192
|
|
|
|
|
|
|
if ( $side =~ /^right$/i ) |
193
|
|
|
|
|
|
|
{ |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
#get the right startposition |
196
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_max'}; |
197
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - $h / 2; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
#get the delta values |
200
|
|
|
|
|
|
|
$height = $self->{'curr_y_max'} - $self->{'curr_y_min'}; |
201
|
|
|
|
|
|
|
$delta = ($height) / ( $self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1 ); |
202
|
|
|
|
|
|
|
$y1 -= ( $delta / 2 ); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
#look if skipping is desired |
205
|
|
|
|
|
|
|
if ( !defined( $self->{'skip_y_ticks'} ) ) |
206
|
|
|
|
|
|
|
{ |
207
|
|
|
|
|
|
|
$self->{'skip_y_ticks'} = 1; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
#draw the labels |
211
|
|
|
|
|
|
|
for ( 0 .. int( ( $self->{'num_datapoints'} - 1 ) / $self->{'skip_y_ticks'} ) ) |
212
|
|
|
|
|
|
|
{ |
213
|
|
|
|
|
|
|
$y2 = $y1 - ($delta) * ( $_ * $self->{'skip_y_ticks'} ); |
214
|
|
|
|
|
|
|
$x2 = $x1 + $self->{'tick_len'} + $self->{'text_space'}; |
215
|
|
|
|
|
|
|
$self->{'gd_obj'} |
216
|
|
|
|
|
|
|
->string( $font, $x2, $y2, $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ), $textcolor ); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#draw the ticks |
220
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_max'}; |
221
|
|
|
|
|
|
|
$x2 = $self->{'curr_x_max'} + $self->{'tick_len'}; |
222
|
|
|
|
|
|
|
$y1 += $h / 2; |
223
|
|
|
|
|
|
|
for ( 0 .. ( $self->{'num_datapoints'} - 1 / $self->{'skip_y_ticks'} ) ) |
224
|
|
|
|
|
|
|
{ |
225
|
|
|
|
|
|
|
$y2 = $y1 - ( $delta * $_ ); |
226
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x1, $y2, $x2, $y2, $misccolor ); |
227
|
|
|
|
|
|
|
if ( $self->true( $self->{'grid_lines'} ) |
228
|
|
|
|
|
|
|
or $self->true( $self->{'x_grid_lines'} ) ) |
229
|
|
|
|
|
|
|
{ |
230
|
|
|
|
|
|
|
$self->{'grid_data'}->{'y'}->[$_] = $y2; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
elsif ( $side =~ /^both$/i ) |
236
|
|
|
|
|
|
|
{ |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
#get the right startposition |
239
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_max'}; |
240
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - $h / 2; |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
#get the delta values |
243
|
|
|
|
|
|
|
$height = $self->{'curr_y_max'} - $self->{'curr_y_min'}; |
244
|
|
|
|
|
|
|
$delta = ($height) / ( $self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1 ); |
245
|
|
|
|
|
|
|
$y1 -= ( $delta / 2 ); |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
#look if skipping is desired |
248
|
|
|
|
|
|
|
if ( !defined( $self->{'skip_y_ticks'} ) ) |
249
|
|
|
|
|
|
|
{ |
250
|
|
|
|
|
|
|
$self->{'skip_y_ticks'} = 1; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
#first draw the right labels |
254
|
|
|
|
|
|
|
for ( 0 .. int( ( $self->{'num_datapoints'} - 1 ) / $self->{'skip_y_ticks'} ) ) |
255
|
|
|
|
|
|
|
{ |
256
|
|
|
|
|
|
|
$y2 = $y1 - ($delta) * ( $_ * $self->{'skip_y_ticks'} ); |
257
|
|
|
|
|
|
|
$x2 = $x1 + $self->{'tick_len'} + $self->{'text_space'}; |
258
|
|
|
|
|
|
|
$self->{'gd_obj'} |
259
|
|
|
|
|
|
|
->string( $font, $x2, $y2, $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ), $textcolor ); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
#then draw the right ticks |
263
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_max'}; |
264
|
|
|
|
|
|
|
$x2 = $self->{'curr_x_max'} + $self->{'tick_len'}; |
265
|
|
|
|
|
|
|
$y1 += $h / 2; |
266
|
|
|
|
|
|
|
for ( 0 .. ( $self->{'num_datapoints'} - 1 / $self->{'skip_y_ticks'} ) ) |
267
|
|
|
|
|
|
|
{ |
268
|
|
|
|
|
|
|
$y2 = $y1 - ( $delta * $_ ); |
269
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x1, $y2, $x2, $y2, $misccolor ); |
270
|
|
|
|
|
|
|
if ( $self->true( $self->{'grid_lines'} ) |
271
|
|
|
|
|
|
|
or $self->true( $self->{'x_grid_lines'} ) ) |
272
|
|
|
|
|
|
|
{ |
273
|
|
|
|
|
|
|
$self->{'grid_data'}->{'y'}->[$_] = $y2; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
#get the right startposition |
278
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
279
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - $h / 2; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
#get the delta values for positioning |
282
|
|
|
|
|
|
|
$height = $self->{'curr_y_max'} - $self->{'curr_y_min'}; |
283
|
|
|
|
|
|
|
$delta = ($height) / ( $self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1 ); |
284
|
|
|
|
|
|
|
$y1 -= ( $delta / 2 ); |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
#then draw the left labels |
287
|
|
|
|
|
|
|
for ( 0 .. int( ( $self->{'num_datapoints'} - 1 ) / $self->{'skip_y_ticks'} ) ) |
288
|
|
|
|
|
|
|
{ |
289
|
|
|
|
|
|
|
$y2 = $y1 - ($delta) * ( $_ * $self->{'skip_y_ticks'} ); |
290
|
|
|
|
|
|
|
$x2 = |
291
|
|
|
|
|
|
|
$x1 - |
292
|
|
|
|
|
|
|
$w * length( $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ) ) #print the Labels right-sided |
293
|
|
|
|
|
|
|
+ $w * $self->{'x_tick_label_length'}; |
294
|
|
|
|
|
|
|
$self->{'gd_obj'} |
295
|
|
|
|
|
|
|
->string( $font, $x2, $y2, $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ), $textcolor ); |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
#update the curr_x_min val |
299
|
|
|
|
|
|
|
$self->{'curr_x_min'} = $x1 + $self->{'text_space'} + $w * $self->{'x_tick_label_length'} + $self->{'tick_len'}; |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
#finally draw the left ticks |
302
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
303
|
|
|
|
|
|
|
$x2 = $self->{'curr_x_min'} - $self->{'tick_len'}; |
304
|
|
|
|
|
|
|
$y1 += $h / 2; |
305
|
|
|
|
|
|
|
for ( 0 .. ( $self->{'num_datapoints'} - 1 / $self->{'skip_y_ticks'} ) ) |
306
|
|
|
|
|
|
|
{ |
307
|
|
|
|
|
|
|
$y2 = $y1 - ( $delta * $_ ); |
308
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x1, $y2, $x2, $y2, $misccolor ); |
309
|
|
|
|
|
|
|
if ( $self->true( $self->{'grid_lines'} ) |
310
|
|
|
|
|
|
|
or $self->true( $self->{'x_grid_lines'} ) ) |
311
|
|
|
|
|
|
|
{ |
312
|
|
|
|
|
|
|
$self->{'grid_data'}->{'y'}->[$_] = $y2; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
else |
318
|
|
|
|
|
|
|
{ |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
#get the right startposition |
321
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
322
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - $h / 2; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
#get the delta values for positioning |
325
|
|
|
|
|
|
|
$height = $self->{'curr_y_max'} - $self->{'curr_y_min'}; |
326
|
|
|
|
|
|
|
$delta = ($height) / ( $self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1 ); |
327
|
|
|
|
|
|
|
$y1 -= ( $delta / 2 ); |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
if ( !defined( $self->{'skip_y_ticks'} ) ) |
330
|
|
|
|
|
|
|
{ |
331
|
|
|
|
|
|
|
$self->{'skip_y_ticks'} = 1; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
#draw the labels |
335
|
|
|
|
|
|
|
for ( 0 .. int( ( $self->{'num_datapoints'} - 1 ) / $self->{'skip_y_ticks'} ) ) |
336
|
|
|
|
|
|
|
{ |
337
|
|
|
|
|
|
|
$y2 = $y1 - ($delta) * ( $_ * $self->{'skip_y_ticks'} ); |
338
|
|
|
|
|
|
|
$x2 = |
339
|
|
|
|
|
|
|
$x1 - |
340
|
|
|
|
|
|
|
$w * length( $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ) ) #print the Labels right-sided |
341
|
|
|
|
|
|
|
+ $w * $self->{'x_tick_label_length'}; |
342
|
|
|
|
|
|
|
$self->{'gd_obj'} |
343
|
|
|
|
|
|
|
->string( $font, $x2, $y2, $self->{f_y_tick}->( $data->[0][ $_ * $self->{'skip_y_ticks'} ] ), $textcolor ); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
#update the curr_x_min val |
347
|
|
|
|
|
|
|
$self->{'curr_x_min'} = $x1 + $self->{'text_space'} + $w * $self->{'x_tick_label_length'} + $self->{'tick_len'}; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
#draw the ticks |
350
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
351
|
|
|
|
|
|
|
$x2 = $self->{'curr_x_min'} - $self->{'tick_len'}; |
352
|
|
|
|
|
|
|
$y1 += $h / 2; |
353
|
|
|
|
|
|
|
for ( 0 .. ( $self->{'num_datapoints'} - 1 / $self->{'skip_y_ticks'} ) ) |
354
|
|
|
|
|
|
|
{ |
355
|
|
|
|
|
|
|
$y2 = $y1 - ( $delta * $_ ); |
356
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x1, $y2, $x2, $y2, $misccolor ); |
357
|
|
|
|
|
|
|
if ( $self->true( $self->{'grid_lines'} ) |
358
|
|
|
|
|
|
|
or $self->true( $self->{'x_grid_lines'} ) ) |
359
|
|
|
|
|
|
|
{ |
360
|
|
|
|
|
|
|
$self->{'grid_data'}->{'y'}->[$_] = $y2; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
#now return |
366
|
|
|
|
|
|
|
return 1; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
## @fn private int _find_y_scale() |
370
|
|
|
|
|
|
|
# find good values for the minimum and maximum y-value on the chart |
371
|
|
|
|
|
|
|
# overwrite the find_y_scale function, only to get the right f_x_ticks !!!!! |
372
|
|
|
|
|
|
|
# @return status |
373
|
|
|
|
|
|
|
sub _find_y_scale |
374
|
|
|
|
|
|
|
{ |
375
|
|
|
|
|
|
|
my $self = shift; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# Predeclare vars. |
378
|
|
|
|
|
|
|
my ( $d_min, $d_max ); # Dataset min & max. |
379
|
|
|
|
|
|
|
my ( $p_min, $p_max ); # Plot min & max. |
380
|
|
|
|
|
|
|
my ( $tickInterval, $tickCount ); |
381
|
|
|
|
|
|
|
my @tickLabels; # List of labels for each tick. |
382
|
|
|
|
|
|
|
my $maxtickLabelLen = 0; # The length of the longest tick label. |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Find the datatset minimum and maximum. |
385
|
|
|
|
|
|
|
( $d_min, $d_max ) = $self->_find_y_range(); |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# Force the inclusion of zero if the user has requested it. |
388
|
|
|
|
|
|
|
if ( $self->true( $self->{'include_zero'} ) ) |
389
|
|
|
|
|
|
|
{ |
390
|
|
|
|
|
|
|
if ( ( $d_min * $d_max ) > 0 ) # If both are non zero and of the same sign. |
391
|
|
|
|
|
|
|
{ |
392
|
|
|
|
|
|
|
if ( $d_min > 0 ) # If the whole scale is positive. |
393
|
|
|
|
|
|
|
{ |
394
|
|
|
|
|
|
|
$d_min = 0; |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
else # The scale is entirely negative. |
397
|
|
|
|
|
|
|
{ |
398
|
|
|
|
|
|
|
$d_max = 0; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
if ( $self->{'integer_ticks_only'} =~ /^\d$/ ) |
404
|
|
|
|
|
|
|
{ |
405
|
|
|
|
|
|
|
if ( $self->{'integer_ticks_only'} == 1 ) |
406
|
|
|
|
|
|
|
{ |
407
|
|
|
|
|
|
|
$self->{'integer_ticks_only'} = 'true'; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
else |
410
|
|
|
|
|
|
|
{ |
411
|
|
|
|
|
|
|
$self->{'integer_ticks_only'} = 'false'; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
if ( $self->true( $self->{'integer_ticks_only'} ) ) |
415
|
|
|
|
|
|
|
{ |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
# Allow the dataset range to be overidden by the user. |
418
|
|
|
|
|
|
|
# f_min/max are booleans which indicate that the min & max should not be modified. |
419
|
|
|
|
|
|
|
my $f_min = defined $self->{'min_val'}; |
420
|
|
|
|
|
|
|
$d_min = $self->{'min_val'} if $f_min; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
my $f_max = defined $self->{'max_val'}; |
423
|
|
|
|
|
|
|
$d_max = $self->{'max_val'} if $f_max; |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# Assert against the min is larger than the max. |
426
|
|
|
|
|
|
|
if ( $d_min > $d_max ) |
427
|
|
|
|
|
|
|
{ |
428
|
|
|
|
|
|
|
croak "The the specified 'min_val' & 'max_val' values are reversed (min > max: $d_min>$d_max)"; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# The user asked for integer ticks, force the limits to integers. |
432
|
|
|
|
|
|
|
# & work out the range directly. |
433
|
|
|
|
|
|
|
$p_min = $self->_round2Tick( $d_min, 1, -1 ); |
434
|
|
|
|
|
|
|
$p_max = $self->_round2Tick( $d_max, 1, 1 ); |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
my $skip = $self->{skip_int_ticks}; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
$tickInterval = $skip; |
439
|
|
|
|
|
|
|
$tickCount = ( $p_max - $p_min ) / $skip + 1; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# Now sort out an array of tick labels. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
for ( my $labelNum = $p_min ; $labelNum <= $p_max ; $labelNum += $tickInterval ) |
444
|
|
|
|
|
|
|
{ |
445
|
|
|
|
|
|
|
my $labelText; |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
if ( defined $self->{f_x_tick} ) |
448
|
|
|
|
|
|
|
{ |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# Is _default_f_tick function used? |
451
|
|
|
|
|
|
|
if ( $self->{f_x_tick} == \&_default_f_tick ) |
452
|
|
|
|
|
|
|
{ |
453
|
|
|
|
|
|
|
$labelText = sprintf( "%d", $labelNum ); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
else |
456
|
|
|
|
|
|
|
{ |
457
|
|
|
|
|
|
|
$labelText = $self->{f_x_tick}->($labelNum); |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
else |
462
|
|
|
|
|
|
|
{ |
463
|
|
|
|
|
|
|
$labelText = sprintf( "%d", $labelNum ); |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
#print "labelText = $labelText\n"; |
467
|
|
|
|
|
|
|
push @tickLabels, $labelText; |
468
|
|
|
|
|
|
|
$maxtickLabelLen = length $labelText if $maxtickLabelLen < length $labelText; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
else |
473
|
|
|
|
|
|
|
{ |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
# Allow the dataset range to be overidden by the user. |
476
|
|
|
|
|
|
|
# f_min/max are booleans which indicate that the min & max should not be modified. |
477
|
|
|
|
|
|
|
my $f_min = defined $self->{'min_val'}; |
478
|
|
|
|
|
|
|
$d_min = $self->{'min_val'} if $f_min; |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
my $f_max = defined $self->{'max_val'}; |
481
|
|
|
|
|
|
|
$d_max = $self->{'max_val'} if $f_max; |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# Assert against the min is larger than the max. |
484
|
|
|
|
|
|
|
if ( $d_min > $d_max ) |
485
|
|
|
|
|
|
|
{ |
486
|
|
|
|
|
|
|
croak "The the specified 'min_val' & 'max_val' values are reversed (min > max: $d_min>$d_max)"; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# Calculate the width of the dataset. (posibly modified by the user) |
490
|
|
|
|
|
|
|
my $d_width = $d_max - $d_min; |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# If the width of the range is zero, forcibly widen it |
493
|
|
|
|
|
|
|
# (to avoid division by zero errors elsewhere in the code). |
494
|
|
|
|
|
|
|
if ( 0 == $d_width ) |
495
|
|
|
|
|
|
|
{ |
496
|
|
|
|
|
|
|
$d_min--; |
497
|
|
|
|
|
|
|
$d_max++; |
498
|
|
|
|
|
|
|
$d_width = 2; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# Descale the range by converting the dataset width into |
502
|
|
|
|
|
|
|
# a floating point exponent & mantisa pair. |
503
|
|
|
|
|
|
|
my ( $rangeExponent, $rangeMantisa ) = $self->_sepFP($d_width); |
504
|
|
|
|
|
|
|
my $rangeMuliplier = 10**$rangeExponent; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# Find what tick |
507
|
|
|
|
|
|
|
# to use & how many ticks to plot, |
508
|
|
|
|
|
|
|
# round the plot min & max to suatable round numbers. |
509
|
|
|
|
|
|
|
( $tickInterval, $tickCount, $p_min, $p_max ) = $self->_calcTickInterval( |
510
|
|
|
|
|
|
|
$d_min / $rangeMuliplier, |
511
|
|
|
|
|
|
|
$d_max / $rangeMuliplier, |
512
|
|
|
|
|
|
|
$f_min, $f_max, |
513
|
|
|
|
|
|
|
$self->{'min_y_ticks'}, |
514
|
|
|
|
|
|
|
$self->{'max_y_ticks'} |
515
|
|
|
|
|
|
|
); |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# Restore the tickInterval etc to the correct scale |
518
|
|
|
|
|
|
|
$_ *= $rangeMuliplier foreach ( $tickInterval, $p_min, $p_max ); |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
#get teh precision for the labels |
521
|
|
|
|
|
|
|
my $precision = $self->{'precision'}; |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
# Now sort out an array of tick labels. |
524
|
|
|
|
|
|
|
for ( my $labelNum = $p_min ; $labelNum <= $p_max ; $labelNum += $tickInterval ) |
525
|
|
|
|
|
|
|
{ |
526
|
|
|
|
|
|
|
my $labelText; |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
if ( defined $self->{f_x_tick} ) |
529
|
|
|
|
|
|
|
{ |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# Is _default_f_tick function used? |
532
|
|
|
|
|
|
|
if ( $self->{f_x_tick} == \&_default_f_tick ) |
533
|
|
|
|
|
|
|
{ |
534
|
|
|
|
|
|
|
$labelText = sprintf( "%." . $precision . "f", $labelNum ); |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
else |
537
|
|
|
|
|
|
|
{ |
538
|
|
|
|
|
|
|
$labelText = $self->{f_x_tick}->($labelNum); |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
else |
542
|
|
|
|
|
|
|
{ |
543
|
|
|
|
|
|
|
$labelText = sprintf( "%." . $precision . "f", $labelNum ); |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
#print "labelText = $labelText\n"; |
547
|
|
|
|
|
|
|
push @tickLabels, $labelText; |
548
|
|
|
|
|
|
|
$maxtickLabelLen = length $labelText if $maxtickLabelLen < length $labelText; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
# Store the calculated data. |
553
|
|
|
|
|
|
|
$self->{'min_val'} = $p_min; |
554
|
|
|
|
|
|
|
$self->{'max_val'} = $p_max; |
555
|
|
|
|
|
|
|
$self->{'y_ticks'} = $tickCount; |
556
|
|
|
|
|
|
|
$self->{'y_tick_labels'} = \@tickLabels; |
557
|
|
|
|
|
|
|
$self->{'y_tick_label_length'} = $maxtickLabelLen; |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
# and return. |
560
|
|
|
|
|
|
|
return 1; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
## @fn private _draw_data |
564
|
|
|
|
|
|
|
# finally get around to plotting the data for (horizontal) bars |
565
|
|
|
|
|
|
|
sub _draw_data |
566
|
|
|
|
|
|
|
{ |
567
|
|
|
|
|
|
|
my $self = shift; |
568
|
|
|
|
|
|
|
my $data = $self->{'dataref'}; |
569
|
|
|
|
|
|
|
my $misccolor = $self->_color_role_to_index('misc'); |
570
|
|
|
|
|
|
|
my ( $x1, $x2, $x3, $y1, $y2, $y3 ); |
571
|
|
|
|
|
|
|
my $cut = 0; |
572
|
|
|
|
|
|
|
my ( $width, $height, $delta1, $delta2, $map, $mod, $pink ); |
573
|
|
|
|
|
|
|
my ( $i, $j, $color ); |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
# init the imagemap data field if they wanted it |
576
|
|
|
|
|
|
|
if ( $self->true( $self->{'imagemap'} ) ) |
577
|
|
|
|
|
|
|
{ |
578
|
|
|
|
|
|
|
$self->{'imagemap_data'} = []; |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
# find both delta values ($delta1 for stepping between different |
582
|
|
|
|
|
|
|
# datapoint names, $delta2 for setpping between datasets for that |
583
|
|
|
|
|
|
|
# point) and the mapping constant |
584
|
|
|
|
|
|
|
$width = $self->{'curr_x_max'} - $self->{'curr_x_min'}; |
585
|
|
|
|
|
|
|
$height = $self->{'curr_y_max'} - $self->{'curr_y_min'}; |
586
|
|
|
|
|
|
|
$delta1 = $height / ( $self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1 ); |
587
|
|
|
|
|
|
|
$map = $width / ( $self->{'max_val'} - $self->{'min_val'} ); |
588
|
|
|
|
|
|
|
if ( $self->true( $self->{'spaced_bars'} ) ) |
589
|
|
|
|
|
|
|
{ |
590
|
|
|
|
|
|
|
$delta2 = $delta1 / ( $self->{'num_datasets'} + 2 ); |
591
|
|
|
|
|
|
|
} |
592
|
|
|
|
|
|
|
else |
593
|
|
|
|
|
|
|
{ |
594
|
|
|
|
|
|
|
$delta2 = $delta1 / $self->{'num_datasets'}; |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# get the base x-y values |
598
|
|
|
|
|
|
|
$y1 = $self->{'curr_y_max'} - $delta2; |
599
|
|
|
|
|
|
|
if ( $self->{'min_val'} >= 0 ) |
600
|
|
|
|
|
|
|
{ |
601
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'}; |
602
|
|
|
|
|
|
|
$mod = $self->{'min_val'}; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
elsif ( $self->{'max_val'} <= 0 ) |
605
|
|
|
|
|
|
|
{ |
606
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_max'}; |
607
|
|
|
|
|
|
|
$mod = $self->{'max_val'}; |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
else |
610
|
|
|
|
|
|
|
{ |
611
|
|
|
|
|
|
|
$x1 = $self->{'curr_x_min'} + abs( $map * $self->{'min_val'} ); |
612
|
|
|
|
|
|
|
$mod = 0; |
613
|
|
|
|
|
|
|
$self->{'gd_obj'}->line( $x1, $self->{'curr_y_min'}, $x1, $self->{'curr_y_max'}, $misccolor ); |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
# draw the bars |
617
|
|
|
|
|
|
|
for $i ( 1 .. $self->{'num_datasets'} ) |
618
|
|
|
|
|
|
|
{ |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# get the color for this dataset |
621
|
|
|
|
|
|
|
$color = $self->_color_role_to_index( 'dataset' . ( $i - 1 ) ); |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# draw every bar for this dataset |
624
|
|
|
|
|
|
|
for $j ( 0 .. $self->{'num_datapoints'} ) |
625
|
|
|
|
|
|
|
{ |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# don't try to draw anything if there's no data |
628
|
|
|
|
|
|
|
if ( defined( $data->[$i][$j] ) ) |
629
|
|
|
|
|
|
|
{ |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# find the bounds of the rectangle |
632
|
|
|
|
|
|
|
if ( $self->true( $self->{'spaced_bars'} ) ) |
633
|
|
|
|
|
|
|
{ |
634
|
|
|
|
|
|
|
$y2 = $y1 - ( $j * $delta1 ) - ( $self->{'num_datasets'} * $delta2 ) + ( ( $i - 1 ) * $delta2 ); |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
else |
637
|
|
|
|
|
|
|
{ |
638
|
|
|
|
|
|
|
$y2 = $y1 - ( $j * $delta1 ) - ( $self->{'num_datasets'} * $delta2 ) + ( ($i) * $delta2 ); |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
$x2 = $x1; |
641
|
|
|
|
|
|
|
$y3 = $y2 + $delta2; |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
#cut the bars off, if needed |
644
|
|
|
|
|
|
|
if ( $data->[$i][$j] > $self->{'max_val'} ) |
645
|
|
|
|
|
|
|
{ |
646
|
|
|
|
|
|
|
$x3 = $x1 + ( ( $self->{'max_val'} - $mod ) * $map ) - 1; |
647
|
|
|
|
|
|
|
$cut = 1; |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
elsif ( $data->[$i][$j] < $self->{'min_val'} ) |
650
|
|
|
|
|
|
|
{ |
651
|
|
|
|
|
|
|
$x3 = $x1 + ( ( $self->{'min_val'} - $mod ) * $map ) + 1; |
652
|
|
|
|
|
|
|
$cut = 1; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
else |
655
|
|
|
|
|
|
|
{ |
656
|
|
|
|
|
|
|
$x3 = $x1 + ( ( $data->[$i][$j] - $mod ) * $map ); |
657
|
|
|
|
|
|
|
$cut = 0; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
# draw the bar |
661
|
|
|
|
|
|
|
## y2 and y3 are reversed in some cases because GD's fill |
662
|
|
|
|
|
|
|
## algorithm is lame |
663
|
|
|
|
|
|
|
if ( $data->[$i][$j] < 0 ) |
664
|
|
|
|
|
|
|
{ |
665
|
|
|
|
|
|
|
$self->{'gd_obj'}->filledRectangle( $x3, $y2, $x2, $y3, $color ); |
666
|
|
|
|
|
|
|
if ( $self->true( $self->{'imagemap'} ) ) |
667
|
|
|
|
|
|
|
{ |
668
|
|
|
|
|
|
|
$self->{'imagemap_data'}->[$i][$j] = [ $x3, $y2, $x2, $y3 ]; |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
$self->{'gd_obj'}->filledRectangle( $x3, $y2, $x2, $y3, $color ); |
672
|
|
|
|
|
|
|
if ( $self->true( $self->{'imagemap'} ) ) |
673
|
|
|
|
|
|
|
{ |
674
|
|
|
|
|
|
|
$self->{'imagemap_data'}->[$i][$j] = [ $x3, $y2, $x2, $y3 ]; |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
else |
678
|
|
|
|
|
|
|
{ |
679
|
|
|
|
|
|
|
$self->{'gd_obj'}->filledRectangle( $x2, $y2, $x3, $y3, $color ); |
680
|
|
|
|
|
|
|
if ( $self->true( $self->{'imagemap'} ) ) |
681
|
|
|
|
|
|
|
{ |
682
|
|
|
|
|
|
|
$self->{'imagemap_data'}->[$i][$j] = [ $x2, $y2, $x3, $y3 ]; |
683
|
|
|
|
|
|
|
} |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# now outline it. outline red if the bar had been cut off |
687
|
|
|
|
|
|
|
unless ($cut) |
688
|
|
|
|
|
|
|
{ |
689
|
|
|
|
|
|
|
$self->{'gd_obj'}->rectangle( $x2, $y3, $x3, $y2, $misccolor ); |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
else |
692
|
|
|
|
|
|
|
{ |
693
|
|
|
|
|
|
|
$pink = $self->{'gd_obj'}->colorAllocate( 255, 0, 255 ); |
694
|
|
|
|
|
|
|
$self->{'gd_obj'}->rectangle( $x2, $y3, $x3, $y2, $pink ); |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
else |
699
|
|
|
|
|
|
|
{ |
700
|
|
|
|
|
|
|
if ( $self->true( $self->{'imagemap'} ) ) |
701
|
|
|
|
|
|
|
{ |
702
|
|
|
|
|
|
|
$self->{'imagemap_data'}->[$i][$j] = [ undef(), undef(), undef(), undef() ]; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
# and finaly box it off |
709
|
|
|
|
|
|
|
$self->{'gd_obj'} |
710
|
|
|
|
|
|
|
->rectangle( $self->{'curr_x_min'}, $self->{'curr_y_min'}, $self->{'curr_x_max'}, $self->{'curr_y_max'}, $misccolor ); |
711
|
|
|
|
|
|
|
return; |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
## be a good module and return 1 |
716
|
|
|
|
|
|
|
1; |