File Coverage

blib/lib/Chart/Split.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::Split
3             #
4             # written and maintained by the
5             # @author Chart Group at Geodetic Fundamental Station Wettzell (Chart@fs.wettzell.de)
6             # @date 2012-10-03
7             # @version 2.4.6
8             #
9              
10             ## @class Chart::Split
11             #Split class derived from class Base.
12             #
13             # This class provides all functions which are specific to
14             # splitted plots
15             #
16             package Chart::Split;
17              
18 2     2   5624 use Chart::Base '2.4.6';
  0            
  0            
19             use GD;
20             use Carp;
21             use strict;
22              
23             @Chart::Split::ISA = qw(Chart::Base);
24             $Chart::Split::VERSION = '2.4.6';
25              
26             #>>>>>>>>>>>>>>>>>>>>>>>>>>#
27             # public methods go here #
28             #<<<<<<<<<<<<<<<<<<<<<<<<<<#
29              
30             #>>>>>>>>>>>>>>>>>>>>>>>>>>>#
31             # private methods go here #
32             #<<<<<<<<<<<<<<<<<<<<<<<<<<<#
33              
34             ## @fn private _draw_x_number_ticks
35             #draw the ticks
36             sub _draw_x_number_ticks
37             {
38             my $self = shift;
39             my $data = $self->{'dataref'};
40             my $font = $self->{'tick_label_font'};
41             my $textcolor = $self->_color_role_to_index('text');
42             my $misccolor = $self->_color_role_to_index('misc');
43             my $num_points = $self->{'num_datapoints'};
44             my ( $h, $w, $width, $step, $start, $interval, $label, $stag, @labels );
45             my ( $x_start, $y_start, $y, $x, $lines, $delta, $ticks );
46             my $x_label_len = 1;
47             my $y_label_len = 1;
48             my $x_max = -0x80000000;
49              
50             $self->{'grid_data'}->{'x'} = [];
51              
52             # find the width
53             $width = $self->{'curr_x_max'} - $self->{'curr_x_min'};
54             $width = 1 if $width == 0;
55              
56             # make sure we got a real font
57             unless ( ( ref $font ) eq 'GD::Font' )
58             {
59             croak "The tick label font you specified isn\'t a GD Font object";
60             }
61              
62             # find out how big the font is
63             ( $w, $h ) = ( $font->width, $font->height );
64              
65             unless ( defined $self->{'start'} && defined $self->{'interval'} )
66             {
67             croak "I need two values from you to draw a split chart: start and interval!";
68             }
69             else
70             {
71             $interval = $self->{'interval'};
72             $start = $self->{'start'};
73             $ticks = $self->{'interval_ticks'} - 1;
74             $label = $start;
75             }
76              
77             #look after devision by zero!
78             if ( $ticks == 0 ) { $ticks = 1; }
79              
80             #calculate the step between the ticks
81             $step = $interval / $ticks;
82              
83             for ( 0 .. $ticks )
84             {
85             push @labels, $self->{f_x_tick}->( sprintf( "%." . $self->{'precision'} . "f", $label ) );
86             $label += $step;
87             }
88              
89             #find the biggest x value
90             foreach ( @{ $data->[0] } )
91             {
92             if ( $_ > $x_max )
93             {
94             $x_max = $_;
95             }
96             }
97              
98             #find the length of the x and y labels
99             foreach (@labels)
100             {
101             if ( length($_) > $x_label_len )
102             {
103             $x_label_len = length($_);
104             }
105             }
106              
107             #find the amount of lines
108             $lines = int( ( ( $x_max - $start ) / $interval ) + 0.99999999999 );
109             $lines = 1 if $lines == 0;
110              
111             #find the length, of the label.
112             $y_label_len = length($lines);
113              
114             #get the starting point and the width
115             if ( $lines > 1 )
116             { #if there are y-ticks
117             if ( $self->{'y_axes'} =~ /^right$/i )
118             {
119             $x_start = $self->{'curr_x_min'};
120             $width = $self->{'curr_x_max'} - $x_start - $self->{'text_space'} * 2 - $y_label_len * $w - $self->{'tick_len'};
121              
122             }
123             elsif ( $self->{'y_axes'} =~ /^both$/i )
124             {
125             $x_start = $self->{'curr_x_min'} + ( $w * $y_label_len ) + 2 * $self->{'text_space'} + $self->{'tick_len'};
126             $width = $self->{'curr_x_max'} - $x_start - ( $w * $y_label_len ) - 2 * $self->{'text_space'} - $self->{'tick_len'};
127             }
128             else
129             {
130             $x_start = $self->{'curr_x_min'} + ( $w * $y_label_len ) + 3 * $self->{'text_space'};
131             $width = $self->{'curr_x_max'} - $x_start;
132             }
133             }
134             else
135             { #if there are no y-axes
136             $x_start = $self->{'curr_x_min'};
137             $width = $self->{'curr_x_max'} - $x_start;
138             }
139              
140             #and the y_start value
141             $y_start = $self->{'curr_y_max'} - $h - $self->{'text_space'};
142              
143             #get the delta value
144             $delta = $width / ($ticks);
145              
146             if ( !defined( $self->{'skip_x_ticks'} ) )
147             {
148             $self->{'skip_x_ticks'} = 1;
149             }
150              
151             #draw the labels
152             if ( $self->{'x_ticks'} =~ /^normal$/i )
153             {
154             if ( $self->{'skip_x_ticks'} > 1 )
155             { #draw a normal tick every nth label
156             for ( 0 .. $#labels - 1 )
157             {
158             if ( defined( $labels[ $_ * $self->{'skip_x_ticks'} ] ) )
159             {
160             $x =
161             $x_start +
162             $delta * ( $_ * $self->{'skip_x_ticks'} ) -
163             ( $w * length( $labels[ $_ * $self->{'skip_x_ticks'} ] ) ) / 2;
164             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[ $_ * $self->{'skip_x_ticks'} ], $textcolor );
165             }
166             }
167             }
168             elsif ( $self->{'custom_x_ticks'} )
169             { #draw only the normal ticks they wanted
170             foreach ( @{ $self->{'custom_x_ticks'} } )
171             {
172             if ( defined $labels[$_] )
173             {
174             $x = $x_start + $delta * $_ - ( $w * length( $labels[$_] ) ) / 2;
175             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[$_], $textcolor );
176             }
177             }
178             }
179             else
180             {
181             for ( 0 .. $#labels )
182             { #draw all ticks normal
183             if ( defined $labels[$_] )
184             {
185             $x = $x_start + $delta * ($_) - ( $w * length( $labels[$_] ) ) / 2;
186             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[$_], $textcolor );
187             }
188             }
189             }
190             }
191             elsif ( $self->{'x_ticks'} =~ /^staggered$/i )
192             {
193             $stag = 0;
194             if ( $self->{'skip_x_ticks'} > 1 )
195             { #draw a staggered tick every nth label
196             for ( 0 .. $#labels - 1 )
197             {
198             if ( defined( $labels[ $_ * $self->{'skip_x_ticks'} ] ) )
199             {
200             $x =
201             $x_start +
202             $delta * ( $_ * $self->{'skip_x_ticks'} ) -
203             ( $w * length( $labels[ $_ * $self->{'skip_x_ticks'} ] ) ) / 2;
204             if ( $stag % 2 == 0 )
205             {
206             $y_start -= $self->{'text_space'} + $h;
207             }
208             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[ $_ * $self->{'skip_x_ticks'} ], $textcolor );
209             if ( $stag % 2 == 0 )
210             {
211             $y_start += $self->{'text_space'} + $h;
212             }
213             $stag++;
214             }
215             }
216             }
217             elsif ( $self->{'custom_x_ticks'} )
218             { # draw only the wanted ticks staggered
219             foreach ( sort ( @{ $self->{'custom_x_ticks'} } ) )
220             {
221             if ( defined $labels[$_] )
222             {
223             $x = $x_start + $delta * $_ - ( $w * ( length( $labels[$_] ) ) ) / 2;
224             if ( $stag % 2 == 0 )
225             {
226             $y_start -= $self->{'text_space'} + $h;
227             }
228             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[$_], $textcolor );
229             if ( $stag % 2 == 0 )
230             {
231             $y_start += $self->{'text_space'} + $h;
232             }
233             $stag++;
234             }
235             }
236             }
237             else
238             { # draw all ticks staggered
239             for ( 0 .. $#labels )
240             {
241             if ( defined $labels[$_] )
242             {
243             $x = $x_start + $delta * $_ - ( $w * ( length( $labels[$_] ) ) ) / 2;
244             if ( $stag % 2 == 0 )
245             {
246             $y_start -= $self->{'text_space'} + $h;
247             }
248             $self->{'gd_obj'}->string( $font, $x, $y_start, $labels[$_], $textcolor );
249             if ( $stag % 2 == 0 )
250             {
251             $y_start += $self->{'text_space'} + $h;
252             }
253             $stag++;
254             }
255             }
256             }
257             }
258             elsif ( $self->{'x_ticks'} =~ /^vertical$/i )
259             {
260             $y_start = $self->{'curr_y_max'} - $self->{'text_space'};
261             if ( $self->{'skip_x_ticks'} > 1 )
262             { #draw every nth tick vertical
263             for ( 0 .. $#labels )
264             {
265             if ( defined $_ )
266             {
267             $x = $x_start + $delta * ( $_ * $self->{'skip_x_ticks'} ) - $h / 2;
268             $y = $y_start - ( $x_label_len - length( $labels[ $_ * $self->{'skip_x_ticks'} ] ) ) * $w;
269             $self->{'gd_obj'}->stringUp( $font, $x, $y, $labels[ $_ * $self->{'skip_x_ticks'} ], $textcolor );
270             }
271             }
272             }
273             elsif ( $self->{'custom_x_ticks'} )
274             {
275             foreach ( @{ $self->{'custom_x_ticks'} } )
276             { #draw the ticks they want vertical
277             if ( defined $labels[$_] )
278             {
279             $x = $x_start + $delta * $_ - $h / 2;
280             $y = $y_start - ( $x_label_len - length( $labels[$_] ) ) * $w;
281             $self->{'gd_obj'}->stringUp( $font, $x, $y, $labels[$_], $textcolor );
282             }
283             }
284             }
285             else
286             { # draw all ticks vertical
287             for ( 0 .. $#labels )
288             {
289             if ( defined $labels[$_] )
290             {
291             $x = $x_start + $delta * $_ - $h / 2;
292             $y = $y_start - ( $x_label_len - length( $labels[$_] ) ) * $w;
293             $self->{'gd_obj'}->stringUp( $font, $x, $y, $labels[$_], $textcolor );
294             }
295             }
296             }
297              
298             }
299              
300             #update the borders
301             if ( $self->{'interval_ticks'} > 0 )
302             {
303             if ( $self->{'x_ticks'} =~ /^normal$/i )
304             {
305             $self->{'curr_y_max'} -= $h + $self->{'text_space'} * 2;
306             }
307             elsif ( $self->{'x_ticks'} =~ /^staggered$/i )
308             {
309             $self->{'curr_y_max'} -= 2 * $h + 3 * $self->{'text_space'};
310             }
311             elsif ( $self->{'x_ticks'} =~ /^vertical$/i )
312             {
313             $self->{'curr_y_max'} -= $w * $x_label_len + $self->{'text_space'} * 2;
314             }
315             }
316              
317             #draw the ticks
318             $y_start = $self->{'curr_y_max'};
319             $y = $y_start - $self->{'tick_len'};
320              
321             if ( $self->{'skip_x_ticks'} > 1 )
322             {
323             for ( 0 .. int( ($#labels) / $self->{'skip_x_ticks'} ) )
324             {
325             $x = $x_start + $delta * ( $_ * $self->{'skip_x_ticks'} );
326             $self->{'gd_obj'}->line( $x, $y_start, $x, $y, $misccolor );
327             if ( $self->true( $self->{'grid_lines'} )
328             or $self->true( $self->{'x_grid_lines'} ) )
329             {
330             $self->{'grid_data'}->{'x'}->[$_] = $x;
331             }
332             }
333             }
334             elsif ( $self->{'custom_x_ticks'} )
335             {
336             foreach ( @{ $self->{'custom_x_ticks'} } )
337             {
338             if ( $_ <= $ticks )
339             {
340             $x = $x_start + $delta * $_;
341             $self->{'gd_obj'}->line( $x, $y_start, $x, $y, $misccolor );
342             if ( $self->true( $self->{'grid_lines'} )
343             or $self->true( $self->{'x_grid_lines'} ) )
344             {
345             $self->{'grid_data'}->{'x'}->[$_] = $x;
346             }
347             }
348             }
349             }
350             else
351             {
352             for ( 0 .. $#labels )
353             {
354             $x = $x_start + $_ * $delta;
355             $self->{'gd_obj'}->line( $x, $y_start, $x, $y, $misccolor );
356             if ( $self->true( $self->{'grid_lines'} )
357             or $self->true( $self->{'x_grid_lines'} ) )
358             {
359             $self->{'grid_data'}->{'x'}->[$_] = $x;
360             }
361             }
362             }
363              
364             #another update of the borders
365             $self->{'curr_y_max'} -= $self->{'tick_len'} if $self->{'interval_ticks'} > 0;
366              
367             #finally return
368             return;
369             }
370              
371             ## @fn private _draw_x_ticks
372             # override the function implemented in base
373             sub _draw_x_ticks
374             {
375             my $self = shift;
376              
377             #Use always the _draw_x_tick funktion because we always do a xy_plot!!!
378             $self->_draw_x_number_ticks();
379              
380             #and return
381             return 1;
382             }
383              
384             ## @fn private _draw_y_ticks
385             # override the function implemented in base
386             sub _draw_y_ticks
387             {
388             my $self = shift;
389             my $side = shift || 'left';
390             my $data = $self->{'dataref'};
391             my $font = $self->{'tick_label_font'};
392             my $textcolor = $self->_color_role_to_index('text');
393             my $misccolor = $self->_color_role_to_index('misc');
394             my @labels = @{ $self->{'y_tick_labels'} };
395             my $num_points = $self->{'num_datapoints'};
396             my ( $w, $h );
397             my ( $x_start, $x, $y_start, $y, $start, $interval );
398             my ( $height, $delta, $label, $lines, $label_len );
399             my ( $s, $f );
400             my $x_max = -0x80000000;
401             $self->{grid_data}->{'y'} = [];
402             $self->{grid_data}->{'y2'} = [];
403              
404             # find the height
405             $height = $self->{'curr_y_max'} - $self->{'curr_y_min'};
406              
407             # make sure we got a real font
408             unless ( ( ref $font ) eq 'GD::Font' )
409             {
410             croak "The tick label font you specified isn\'t a GD Font object";
411             }
412              
413             # find out how big the font is
414             ( $w, $h ) = ( $font->width, $font->height );
415              
416             #get the base variables
417             $interval = $self->{'interval'};
418             $start = $self->{'start'};
419              
420             #find the biggest x value
421             foreach ( @{ $data->[0] } )
422             {
423             if ( $_ > $x_max )
424             {
425             $x_max = $_;
426             }
427             }
428              
429             #calculate the number of lines and the length
430             $lines = int( ( ( $x_max - $start ) / $interval ) + 0.99999999999 );
431             $lines = 1 if $lines == 0;
432             $label_len = length($lines);
433              
434             #get the space between two lines
435             $delta = $height / $lines;
436              
437             #now draw them
438             if ( $lines > 1 )
439             {
440             if ( $side =~ /^right$/i )
441             {
442              
443             #get the starting point
444             $x_start = $self->{'curr_x_max'};
445             $y_start = $self->{'curr_y_min'};
446              
447             #draw the labels
448             for $label ( 0 .. $lines - 1 )
449             {
450             $x = $x_start - $self->{'text_space'} - $label_len * $w;
451             $y = $y_start + $label * $delta + $delta / 2 - $h / 2;
452             $self->{'gd_obj'}->string( $font, $x, $y, $label, $textcolor );
453             }
454              
455             #draw the ticks
456             for $label ( 0 .. $lines )
457             {
458             $x = $x_start - $self->{'text_space'} * 2 - $label_len * $w - $self->{'tick_len'};
459             $y = $y_start + $label * $delta;
460             $self->{'gd_obj'}->line( $x_start - $self->{'text_space'}, $y, $x, $y, $misccolor );
461              
462             #add data for grid_lines
463             push @{ $self->{grid_data}->{'y'} }, $y;
464             }
465              
466             #update the borders
467             $self->{'curr_x_max'} = $x_start - $self->{'text_space'} * 2 - $label_len * $w - $self->{'tick_len'};
468              
469             }
470              
471             elsif ( $side =~ /^both$/i )
472             {
473              
474             #get the starting point
475             $x_start = $self->{'curr_x_min'};
476             $y_start = $self->{'curr_y_min'};
477              
478             #first the left side
479             #draw the labels
480             for $label ( 0 .. $lines - 1 )
481             {
482             $x = $self->{'curr_x_min'} + $self->{'text_space'} * 2;
483             $y = $y_start + $label * $delta + $delta / 2 - $h / 2;
484             $self->{'gd_obj'}->string( $font, $x, $y, $self->{'f_y_tick'}->($label), $textcolor );
485             }
486              
487             #draw the ticks
488             for $label ( 0 .. $lines )
489             {
490             $x = $x_start + $self->{'text_space'} * 2 + $label_len * $w + $self->{'tick_len'};
491             $y = $y_start + $label * $delta;
492             $self->{'gd_obj'}->line( $x_start + $self->{'text_space'}, $y, $x, $y, $misccolor );
493             }
494              
495             #then the right side
496             #get the starting point
497             $x_start = $self->{'curr_x_max'};
498             $y_start = $self->{'curr_y_min'};
499              
500             #draw the labels
501             for $label ( 0 .. $lines - 1 )
502             {
503             $x = $x_start - $self->{'text_space'} - $label_len * $w;
504             $y = $y_start + $label * $delta + $delta / 2 - $h / 2;
505             $self->{'gd_obj'}->string( $font, $x, $y, $self->{'f_y_tick'}->($label), $textcolor );
506             }
507              
508             #draw the ticks
509             for $label ( 0 .. $lines )
510             {
511             $x = $x_start - $self->{'text_space'} * 2 - $label_len * $w - $self->{'tick_len'};
512             $y = $y_start + $label * $delta;
513             $self->{'gd_obj'}->line( $x_start - $self->{'text_space'}, $y, $x, $y, $misccolor );
514              
515             #add data for grid_lines
516             push @{ $self->{grid_data}->{'y'} }, $y;
517             }
518              
519             #update the borders
520             $self->{'curr_x_min'} += $self->{'text_space'} * 2 + $label_len * $w + $self->{'tick_len'};
521             $self->{'curr_x_max'} = $x_start - $self->{'text_space'} * 2 - $label_len * $w - $self->{'tick_len'};
522              
523             }
524             else
525             {
526              
527             #get the starting point
528             $x_start = $self->{'curr_x_min'};
529             $y_start = $self->{'curr_y_min'};
530              
531             #draw the labels
532             for $label ( 0 .. $lines - 1 )
533             {
534             $x = $self->{'curr_x_min'} + $self->{'text_space'} * 2;
535             $y = $y_start + $label * $delta + $delta / 2 - $h / 2;
536             $self->{'gd_obj'}->string( $font, $x, $y, $self->{'f_y_tick'}->($label), $textcolor );
537             }
538              
539             #draw the ticks
540             for $label ( 0 .. $lines )
541             {
542             $x = $x_start + $label_len * $w + $self->{'tick_len'} + $self->{'text_space'} * 3;
543             $y = $y_start + $label * $delta;
544             $self->{'gd_obj'}->line( $x_start + $self->{'text_space'}, $y, $x, $y, $misccolor );
545              
546             #this is also where we have to draw the grid_lines
547             push @{ $self->{grid_data}->{'y'} }, $y;
548             }
549              
550             #update the borders
551             $self->{'curr_x_min'} = $x_start + $self->{'text_space'} * 3 + $label_len * $w;
552             }
553              
554             }
555              
556             #finally return
557             return 1;
558             }
559              
560             ## @fn private _draw_data
561             # plot the data
562             sub _draw_data
563             {
564             my $self = shift;
565             my $data = $self->{'dataref'};
566             my $misccolor = $self->_color_role_to_index('misc');
567             my $num_points = $self->{'num_datapoints'};
568             $num_points = 1 if $num_points == 0;
569             my $num_sets = $self->{'num_datasets'};
570             $num_sets = 1 if $num_sets == 0;
571             my ( $lines, $split, $width, $height, $delta_lines, $delta_sets, $map, $last_line );
572             my ( $akt_line, $akt_set, $akt_point, $color, $x_start, $y_start, $x, $y );
573             my ( $x_last, $y_last, $delta_point, $brush, $mod, $x_interval, $start );
574             my $i = 0;
575             my $interval = ( $self->{'max_val'} - $self->{'min_val'} );
576             $interval = 1 if $interval == 0;
577             my $x_max = -0x80000000;
578              
579             # find the height and the width
580             $width = $self->{'curr_x_max'} - $self->{'curr_x_min'};
581             $width = 1 if $width == 0;
582             $height = $self->{'curr_y_max'} - $self->{'curr_y_min'};
583             $height = 1 if $height == 0;
584              
585             # init the imagemap data field if they asked for it
586             if ( $self->true( $self->{'imagemap'} ) )
587             {
588             $self->{'imagemap_data'} = [];
589             }
590              
591             #get the base values
592             $x_interval = $self->{'interval'};
593             $x_interval = 1 if $x_interval == 0;
594             $start = $self->{'start'};
595              
596             #find the biggest x value
597             foreach ( @{ $data->[0] } )
598             {
599             if ( $_ > $x_max )
600             {
601             $x_max = $_;
602             }
603             }
604              
605             #calculate the number of lines
606             $lines = int( ( ( $x_max - $start ) / $x_interval ) + 0.99999999999 );
607             $lines = 1 if $lines == 0;
608              
609             #find delta_lines for the space between the lines
610             #and delta_sets for the space of the datasets of one line
611             #and the delta_point for the space between the datapoints
612             $delta_lines = $height / $lines;
613             $delta_sets = $delta_lines / $num_sets;
614             $delta_point = $width / ($x_interval);
615              
616             #find $map, for the y values
617             $map = $delta_sets / $interval;
618              
619             #find the mod and the y_start value
620             #correct the start value, if scale is set! Otherwise the plot is to high or to low!
621             #The corecction, isn't perfect, but it does a good job in most cases.
622             if ( $self->{'min_val'} >= 0 )
623             {
624             $mod = $self->{'min_val'};
625             if ( $self->{'scale'} > 1 )
626             {
627             $y_start = $self->{'curr_y_min'} + ( $interval * $map / 2 ) * ( $self->{'scale'} - 1 );
628             }
629             else
630             {
631             $y_start = $self->{'curr_y_min'};
632             }
633             }
634             elsif ( $self->{'max_val'} <= 0 )
635             {
636             $mod = $self->{'min_val'};
637             if ( $self->{'scale'} > 1 )
638             {
639             $y_start = $self->{'curr_y_min'} + ( $interval * $map / 2 ) * ( $self->{'scale'} - 1 );
640             }
641             else
642             {
643             $y_start = $self->{'curr_y_min'};
644             }
645             }
646             else
647             {
648             $y_start = $self->{'curr_y_min'} + ( $map * $self->{'min_val'} );
649             $mod = 0;
650             }
651              
652             #The upper right corner is the point, where we start
653             $x_start = $self->{'curr_x_min'};
654              
655             #draw the lines
656             for $akt_set ( 0 .. $num_sets - 1 )
657             {
658             for $akt_point ( 0 .. $self->{'num_datapoints'} - 1 )
659             {
660              
661             #get the color for this dataset
662             $color = $self->_color_role_to_index( 'dataset' . $akt_set );
663             $brush = $self->_prepare_brush( $color, 'line' );
664             $self->{'gd_obj'}->setBrush($brush);
665              
666             #start with the first point at line number zero
667             $last_line = 0;
668             for $akt_line ( $last_line .. $lines - 1 )
669             {
670              
671             #update the last line. That makes it a little bit faster.
672             $last_line = $akt_line;
673              
674             #Don't try to draw, if there is no data
675             if ( defined $data->[0][$akt_point] )
676             {
677             if ( $data->[0][$akt_point] <= ( ( $akt_line + 1 ) * $x_interval + $start )
678             && $data->[0][$akt_point] >= $akt_line * $x_interval + $start )
679             {
680              
681             #the current point
682             $x = $x_start + ( $data->[0][$akt_point] - ( $akt_line * $x_interval ) - ($start) ) * $delta_point;
683             $y =
684             $y_start +
685             $akt_line * $delta_lines +
686             $akt_set * $delta_sets +
687             $delta_sets -
688             ( $data->[ 1 + $akt_set ][$akt_point] - $mod ) * $map * $self->{'scale'};
689              
690             #draw the line
691             $self->{'gd_obj'}->line( $x_last, $y_last, $x, $y, gdBrushed ) if $akt_point != 0;
692              
693             #calculate the start point for the next line
694             #first if the next point is in the same line
695             if ( defined( $data->[0][ $akt_point + 1 ] )
696             && $data->[0][ $akt_point + 1 ] <= ( ( $akt_line + 1 ) * $x_interval + $start )
697             && $data->[0][ $akt_point + 1 ] > $akt_line * $x_interval + $start )
698             {
699             $x_last = $x;
700             $y_last = $y;
701             }
702              
703             #second, if the next point is not in the same line
704             else
705             {
706             $x_last = $self->{'curr_x_min'};
707             $y_last =
708             $y_start +
709             ( $akt_line + 1 ) * $delta_lines +
710             $akt_set * $delta_sets +
711             $delta_sets -
712             ( $data->[ 1 + $akt_set ][$akt_point] - $mod ) * $map * $self->{'scale'};
713             }
714              
715             # store the imagemap data if they asked for it
716             if ( $self->true( $self->{'imagemap'} ) )
717             {
718             $self->{'imagemap_data'}->[$akt_set][ $akt_point - 1 ] = [ $x_last, $y_last ];
719             $self->{'imagemap_data'}->[$akt_set][$akt_point] = [ $x, $y ];
720             }
721             }
722             else
723             { #Go to the next line. Maybe the current point is in that line!
724             next;
725             }
726             }
727             else
728             {
729             if ( $self->true( $self->{'imagemap'} ) )
730             {
731             $self->{'imagemap_data'}->[$akt_set][ $akt_point - 1 ] = [ undef(), undef() ];
732             $self->{'imagemap_data'}->[$akt_set][$akt_point] = [ undef(), undef() ];
733             }
734             }
735             }
736             }
737             }
738              
739             $y_start = $self->{'curr_y_min'};
740              
741             #draw some nice little lines
742             for $akt_set ( 0 .. $num_sets - 1 )
743             {
744             for $akt_line ( 0 .. $lines - 1 )
745             {
746              
747             #draw a line between the sets at the left side of the chart
748             $self->{'gd_obj'}->line(
749             $x_start,
750             $y_start + $akt_line * $delta_lines + $akt_set * $delta_sets,
751             $x_start + $self->{'tick_len'},
752             $y_start + $akt_line * $delta_lines + $akt_set * $delta_sets, $misccolor
753             );
754              
755             #draw a line between the sets at the right side of the chart
756             $self->{'gd_obj'}->line(
757             $self->{'curr_x_max'},
758             $y_start + $akt_line * $delta_lines + $akt_set * $delta_sets,
759             $self->{'curr_x_max'} - $self->{'tick_len'},
760             $y_start + $akt_line * $delta_lines + $akt_set * $delta_sets, $misccolor
761             );
762             }
763             }
764              
765             #Box it off
766             $self->{'gd_obj'}
767             ->rectangle( $self->{'curr_x_min'}, $self->{'curr_y_min'}, $self->{'curr_x_max'}, $self->{'curr_y_max'}, $misccolor );
768              
769             #finally retrun
770             return;
771             }
772              
773             #be a good modul and return 1
774             1;
775