| 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; |