File Coverage

blib/lib/Chart/LinesPoints.pm
Criterion Covered Total %
statement 93 146 63.7
branch 30 56 53.6
condition 8 21 38.1
subroutine 6 6 100.0
pod n/a
total 137 229 59.8


line stmt bran cond sub pod time code
1             #====================================================================
2             # Chart::LinesPoints
3             #
4             # written by david bonner
5             # dbonner@cs.bu.edu
6             #
7             # maintained by the Chart Group
8             # Chart@wettzell.ifag.de
9             #
10             #---------------------------------------------------------------------
11             # History:
12             #----------
13             # $RCSfile: LinesPoints.pm,v $ $Revision: 1.4 $ $Date: 2003/02/14 14:10:36 $
14             # $Author: dassing $
15             # $Log: LinesPoints.pm,v $
16             # Revision 1.4 2003/02/14 14:10:36 dassing
17             # First setup to cvs
18             #
19             #====================================================================
20             package Chart::LinesPoints;
21              
22 8     8   202 use Chart::Base 2.3;
  8         206  
  8         133  
23 8     8   194 use GD;
  8         164  
  8         156  
24 8     8   293 use Carp;
  8         72  
  8         138  
25 8     8   123 use strict;
  8         73  
  8         109  
26              
27             @Chart::LinesPoints::ISA = qw(Chart::Base);
28             $Chart::LinesPoints::VERSION = '2.3';
29              
30             #>>>>>>>>>>>>>>>>>>>>>>>>>>#
31             # public methods go here #
32             #<<<<<<<<<<<<<<<<<<<<<<<<<<#
33              
34              
35              
36             #>>>>>>>>>>>>>>>>>>>>>>>>>>>#
37             # private methods go here #
38             #<<<<<<<<<<<<<<<<<<<<<<<<<<<#
39              
40             ## finally get around to plotting the data
41             sub _draw_data {
42 8     8   104   my $self = shift;
43 8         82   my $data = $self->{'dataref'};
44 8         107   my $misccolor = $self->_color_role_to_index('misc');
45 8         352   my ($x1, $x2, $x3, $y1, $y2, $y3, $mod, $abs_x_max, $abs_y_max);
46 8         78   my ($width, $height, $delta, $map, $t_x_min, $t_x_max, $t_y_min, $t_y_max);
47 8         100   my ($i, $j, $color, $brush, $zero_offset, $delta_num);
48 8         75   my $repair_top_flag = 0;
49 8         72   my $repair_bottom_flag = 0;
50 8         71   my $diff;
51               
52             # init the imagemap data field if they want it
53 8 50       103   if ($self->{'imagemap'} =~ /^true$/i) {
54 0         0     $self->{'imagemap_data'} = [];
55               }
56              
57             # find the delta value between data points, as well
58             # as the mapping constant
59 8         88   $width = $self->{'curr_x_max'} - $self->{'curr_x_min'};
60 8         83   $height = $self->{'curr_y_max'} - $self->{'curr_y_min'};
61 8 50       164   $delta = $width / ($self->{'num_datapoints'} > 0 ? $self->{'num_datapoints'} : 1);
62 8         82   $diff = ($self->{'max_val'} - $self->{'min_val'});
63 8 50       264   $diff = 1 if $diff == 0;
64 8         115   $map = $height / $diff;
65              
66             # get the base x-y values
67 8 100       100   if ($self->{'xy_plot'} =~ /^true$/i) {
68 1         10     $x1 = $self->{'curr_x_min'};
69               }
70               else {
71 7         80     $x1 = $self->{'curr_x_min'} + ($delta / 2);
72               }
73 8 100       239   if ($self->{'min_val'} >= 0) {
    50          
74 7         71     $y1 = $self->{'curr_y_max'};
75 7         69     $mod = $self->{'min_val'};
76               }
77               elsif ($self->{'max_val'} <= 0) {
78 1         11     $y1 = $self->{'curr_y_min'};
79 1         10     $mod = $self->{'max_val'};
80               }
81               else {
82 0         0     $y1 = $self->{'curr_y_min'} + ($map * $self->{'max_val'});
83 0         0     $mod = 0;
84 0         0     $self->{'gd_obj'}->line ($self->{'curr_x_min'}, $y1,
85                                          $self->{'curr_x_max'}, $y1,
86                                          $misccolor);
87               }
88              
89             #for a xy-plot, use this delta and maybe an offset for the zero-axes
90 8 100       127   if ($self->{'xy_plot'} =~ /^true$/i ) {
91 1         10     $diff = ($self->{'x_max_val'} - $self->{'x_min_val'});
92 1 50       12     $diff = 1 if $diff == 0;
93 1         11     $delta_num = $width / ($self->{'x_max_val'} - $self->{'x_min_val'});
94              
95 1 50 33     16     if ($self->{'x_min_val'} <= 0 && $self->{'x_max_val'} >= 0) {
    0 0        
96 1         12        $zero_offset = abs($self->{'x_min_val'}) * abs($delta_num);
97                 }
98                 elsif ($self->{'x_min_val'} > 0 || $self->{'x_max_val'} < 0) {
99 0         0        $zero_offset = -$self->{'x_min_val'} * $delta_num;
100                 }
101                 else {
102 0         0        $zero_offset = 0;
103                 }
104               }
105               
106             # draw the lines
107 8         92   for $i (1..$self->{'num_datasets'}) {
108             # get the color for this dataset, and set the brush
109 18         297     $color = $self->_color_role_to_index('dataset'.($i-1));
110 18         203     $brush = $self->_prepare_brush ($color, 'line');
111 18         385     $self->{'gd_obj'}->setBrush ($brush);
112              
113             # draw every line for this dataset
114 18         180     for $j (1..$self->{'num_datapoints'}) {
115             # don't try to draw anything if there's no data
116 183 100 66     4621       if (defined ($data->[$i][$j]) and defined ($data->[$i][$j-1])) {
117 165 100       2007         if ($self->{'xy_plot'} =~ /^true$/i ) {
118 60         584            $x2 = $x1 + $delta_num * $data->[0][$j-1] + $zero_offset;
119 60         599            $x3 = $x1 + $delta_num * $data->[0][$j] + $zero_offset;
120                     }
121                     else {
122 105         927            $x2 = $x1 + ($delta * ($j - 1));
123 105         919            $x3 = $x1 + ($delta * $j);
124                     }
125 165         1699 $y2 = $y1 - (($data->[$i][$j-1] - $mod) * $map);
126 165         1538 $y3 = $y1 - (($data->[$i][$j] - $mod) * $map);
127              
128             #set the flags, if the lines are out of the borders of the chart
129 165 50 33     4007         if ( ($data->[$i][$j] > $self->{'max_val'}) || ($data->[$i][$j-1] > $self->{'max_val'}) ) {
130 0         0            $repair_top_flag = 1;
131                     }
132              
133 165 50 33     2015         if ( ($self->{'max_val'} <= 0) &&
      66        
134                          (($data->[$i][$j] > $self->{'max_val'}) || ($data->[$i][$j-1] > $self->{'max_val'})) ) {
135 0         0            $repair_top_flag = 1;
136                     }
137 165 50 33     2583         if ( ($data->[$i][$j] < $self->{'min_val'}) || ($data->[$i][$j-1] < $self->{'min_val'}) ) {
138 0         0            $repair_bottom_flag = 1;
139                     }
140              
141             # draw the line
142 165         1803 $self->{'gd_obj'}->line($x2, $y2, $x3, $y3, gdBrushed);
143                   }
144                 }
145              
146             # reset the brush for points
147 18         241     $brush = $self->_prepare_brush ($color, 'point');
148 18         494     $self->{'gd_obj'}->setBrush ($brush);
149              
150             # draw every point for this dataset
151 18         194     for $j (0..$self->{'num_datapoints'}) {
152             # don't try to draw anything if there's no data
153 201 100       3114       if (defined ($data->[$i][$j])) {
154 183 100       1881         if ($self->{'xy_plot'} =~ /^true$/i ) {
155 62         586            $x2 = $x1 + $delta_num * $data->[0][$j] + $zero_offset;
156 62         546            $x3 = $x2 ;
157                     }
158                     else {
159 121         1002            $x2 = $x1 + ($delta * $j);
160 121         1077            $x3 = $x2;
161                     }
162 183         1734         $y2 = $y1 - (($data->[$i][$j] - $mod) * $map);
163 183         1867         $y3 = $y2;
164              
165             # draw the point
166 183         8827         $self->{'gd_obj'}->line($x2, $y2, $x3, $y3, gdBrushed);
167              
168             # remember the imagemap data if they wanted it
169 183 50       2903 if ($self->{'imagemap'} =~ /^true$/i) {
170 0         0 $self->{'imagemap_data'}->[$i][$j] = [ $x2, $y2 ];
171             }
172                   } else {
173 18 50       260 if ($self->{'imagemap'} =~ /^true$/i) {
174 0         0 $self->{'imagemap_data'}->[$i][$j] = [ undef(), undef() ];
175                     }
176                   }
177                 }
178               }
179                   
180             # and finaly box it off
181 8         500   $self->{'gd_obj'}->rectangle ($self->{'curr_x_min'},
182                $self->{'curr_y_min'},
183             $self->{'curr_x_max'},
184             $self->{'curr_y_max'},
185             $misccolor);
186              
187             #get the width and the heigth of the complete picture
188 8         113   ($abs_x_max, $abs_y_max) = $self->{'gd_obj'}->getBounds();
189              
190             #repair the chart, if the lines are out of the borders of the chart
191 8 50       145   if ($repair_top_flag) {
192             #overwrite the ugly mistakes
193 0         0    $self->{'gd_obj'}->filledRectangle ($self->{'curr_x_min'}, 0,
194             $self->{'curr_x_max'}, $self->{'curr_y_min'}-2,
195             $self->_color_role_to_index('background'));
196              
197             #save the actual x and y values
198 0         0    $t_x_min = $self->{'curr_x_min'};
199 0         0    $t_x_max = $self->{'curr_x_max'};
200 0         0    $t_y_min = $self->{'curr_y_min'};
201 0         0    $t_y_max = $self->{'curr_y_max'};
202              
203              
204             #get back to the point, where everything began
205 0         0    $self->{'curr_x_min'} = 0;
206 0         0    $self->{'curr_y_min'} = 0;
207 0         0    $self->{'curr_x_max'} = $abs_x_max;
208 0         0    $self->{'curr_y_max'} = $abs_y_max;
209              
210             #draw the title again
211 0 0       0    if ($self->{'title'}) {
212 0         0     $self->_draw_title
213                }
214              
215             #draw the sub title again
216 0 0       0    if ($self->{'sub_title'}) {
217 0         0     $self->_draw_sub_title
218                }
219              
220             #draw the top legend again
221 0 0       0    if ($self->{'legend'} =~ /^top$/i) {
222 0         0     $self->_draw_top_legend;
223                }
224              
225             #reset the actual values
226 0         0    $self->{'curr_x_min'} = $t_x_min;
227 0         0    $self->{'curr_x_max'} = $t_x_max;
228 0         0    $self->{'curr_y_min'} = $t_y_min;
229 0         0    $self->{'curr_y_max'} = $t_y_max;
230               }
231              
232 8 50       96   if ($repair_bottom_flag) {
233             #overwrite the ugly mistakes
234 0         0    $self->{'gd_obj'}->filledRectangle ($self->{'curr_x_min'}, $self->{'curr_y_max'}+1,
235             $self->{'curr_x_max'}, $abs_y_max,
236             $self->_color_role_to_index('background'));
237              
238             #save the actual x and y values
239 0         0    $t_x_min = $self->{'curr_x_min'};
240 0         0    $t_x_max = $self->{'curr_x_max'};
241 0         0    $t_y_min = $self->{'curr_y_min'};
242 0         0    $t_y_max = $self->{'curr_y_max'};
243              
244             #get back to the point, where everything began
245 0         0    $self->{'curr_x_min'} = 0;
246 0         0    $self->{'curr_y_min'} = 0;
247 0         0    $self->{'curr_x_max'} = $abs_x_max;
248 0         0    $self->{'curr_y_max'} = $abs_y_max-1;
249              
250             # mark off the graph_border space
251 0         0    $self->{'curr_y_max'} -= 2* $self->{'graph_border'};
252              
253             #draw the bottom legend again
254 0 0       0    if ($self->{'legend'} =~ /^bottom$/i) {
255 0         0     $self->_draw_bottom_legend;
256                }
257              
258             #draw the x label again
259 0 0       0    if ($self->{'x_label'}) {
260 0         0     $self->_draw_x_label;
261                }
262              
263             #get back to the start point for the ticks
264 0         0    $self->{'curr_x_min'} = $self->{'temp_x_min'};
265 0         0    $self->{'curr_y_min'} = $self->{'temp_y_min'};
266 0         0    $self->{'curr_x_max'} = $self->{'temp_x_max'};
267 0         0    $self->{'curr_y_max'} = $self->{'temp_y_max'};
268              
269             #draw the x ticks again
270 0         0    $self->_draw_x_ticks;
271              
272             #reset the actual values
273 0         0    $self->{'curr_x_min'} = $t_x_min;
274 0         0    $self->{'curr_x_max'} = $t_x_max;
275 0         0    $self->{'curr_y_min'} = $t_y_min;
276 0         0    $self->{'curr_y_max'} = $t_y_max;
277               }
278              
279 8         736   return;
280              
281             }
282              
283              
284             ## set the gdBrush object to trick GD into drawing fat lines
285             sub _prepare_brush {
286 46     46   433   my $self = shift;
287 46         456   my $color = shift;
288 46         407   my $type = shift;
289 46         440   my ($radius, @rgb, $brush, $white, $newcolor);
290              
291             # get the rgb values for the desired color
292 46         1736   @rgb = $self->{'gd_obj'}->rgb($color);
293              
294             # get the appropriate brush size
295 46 100       549   if ($type eq 'line') {
    50          
296 18         185     $radius = $self->{'brush_size'}/2;
297         </