1 package Imager::Graph::Line;
5 Imager::Graph::Line - a tool for drawing line charts on Imager images
9 This subclass is still in green development.
16 @ISA = qw(Imager::Graph);
18 =item setYTics($count)
20 Set the number of Y tics to use. Their value and position will be determined by the data range.
25 $_[0]->{'y_tics'} = $_[1];
29 return $_[0]->{'y_tics'};
33 my ($self, %opts) = @_;
35 $self->_processOptions(\%opts);
37 if (!$self->_validInput()) {
41 $self->_style_setup(\%opts);
43 my $style = $self->{_style};
45 my $img = $self->_make_img()
48 my @chart_box = ( 0, 0, $img->getwidth-1, $img->getheight-1 );
50 my @labels = map { $_->{'series_name'} } @{$self->_getDataSeries()};
51 if ($style->{features}{legend} && (scalar @labels)) {
52 $self->_draw_legend($img, \@labels, \@chart_box)
56 my @series = @{$self->_getDataSeries()};
60 foreach my $series (@series) {
61 my @data = @{$series->{'data'}};
63 foreach my $value (@data) {
64 if ($value > $max_value) { $max_value = $value; }
65 if ($value < $min_value) { $min_value = $value; }
69 my $value_range = $max_value - $min_value;
71 my $width = $self->_get_number('width');
72 my $height = $self->_get_number('height');
73 my $size = $self->_get_number('size');
75 my $bottom = ($height - $size) / 2;
76 my $left = ($width - $size) / 2;
78 my @graph_box = ( $left, $bottom, $left + $size - 1, $bottom + $size - 1 );
85 ymax => $bottom+$size,
91 xmax => $left+$size - 1,
93 ymax => $bottom+$size -1 ,
101 xmax => $left+$size - 1,
102 ymin => $bottom + $size - (-1*$min_value / $value_range) * ($size -1),
103 ymax => $bottom+$size -1,
108 if ($self->_getYTics()) {
109 $self->_drawYTics($img, $min_value, $max_value, $self->_getYTics(), \@graph_box, \@chart_box);
111 if ($self->_getLabels()) {
112 $self->_drawXTics($img, \@graph_box, \@chart_box);
115 my $series_counter = 0;
116 foreach my $series (@series) {
117 my @data = @{$series->{'data'}};
118 my $data_size = scalar @data;
119 my @fill = $self->_data_fill($series_counter, \@graph_box);
120 my $color = $self->_data_color($series_counter);
121 for (my $i = 0; $i < $data_size - 1; $i++) {
122 my $x1 = $left + $i * $size / ($data_size - 1);
123 my $x2 = $left + ($i + 1) * $size / ($data_size - 1);
125 my $y1 = $bottom + ($value_range - $data[$i] + $min_value)/$value_range * $size;
126 my $y2 = $bottom + ($value_range - $data[$i + 1] + $min_value)/$value_range * $size;
128 $img->line(x1 => $x1, y1 => $y1, x2 => $x2, y2 => $y2, aa => 1, color => $color) || die $img->errstr;
129 $img->circle(x => $x1, y => $y1, r => 3, aa => 1, filled => 1, @fill);
132 my $x2 = $left + ($data_size - 1) * $size / ($data_size - 1);
133 my $y2 = $bottom + ($value_range - $data[$data_size - 1] + $min_value)/$value_range * $size;
135 $img->circle(x => $x2, y => $y2, r => 3, aa => 1, filled => 1, @fill);
147 my $tic_count = shift;
148 my $graph_box = shift;
149 my $image_box = shift;
151 my $interval = ($max - $min) / ($tic_count - 1);
153 my %text_info = $self->_text_style('legend')
156 my $tic_distance = ($graph_box->[3] - $graph_box->[1]) / ($tic_count - 1);
157 for my $count (0 .. $tic_count - 1) {
158 my $x1 = $graph_box->[0] - 5;
159 my $x2 = $graph_box->[0] + 5;
160 my $y1 = $graph_box->[3] - ($count * $tic_distance);
162 $img->line(x1 => $x1, x2 => $x2, y1 => $y1, y2 => $y1, aa => 1, color => '000000');
164 my $value = sprintf("%.2f", ($count*$interval)+$min);
166 my @box = $self->_text_bbox($value, 'legend')
170 my $height = $box[3];
172 $img->string(%text_info,
173 x => ($x1 - $width - 3),
174 y => ($y1 + ($height / 2)),
184 my $graph_box = shift;
185 my $image_box = shift;
187 my $labels = $self->_getLabels();
189 my $tic_count = (scalar @$labels) - 1;
191 my $tic_distance = ($graph_box->[2] - $graph_box->[0]) / ($tic_count);
192 my %text_info = $self->_text_style('legend')
195 for my $count (0 .. $tic_count) {
196 my $label = $labels->[$count];
197 my $x1 = $graph_box->[0] + ($tic_distance * $count);
198 my $y1 = $graph_box->[3] + 5;
199 my $y2 = $graph_box->[3] - 5;
201 $img->line(x1 => $x1, x2 => $x1, y1 => $y1, y2 => $y2, aa => 1, color => '000000');
203 my @box = $self->_text_bbox($label, 'legend')
207 my $height = $box[3];
209 $img->string(%text_info,
210 x => ($x1 - ($width / 2)),
211 y => ($y1 + ($height + 5)),
221 if (!defined $self->_getDataSeries() || !scalar @{$self->_getDataSeries()}) {
222 return $self->_error("No data supplied");
225 if (!scalar @{$self->_getDataSeries()->[0]->{'data'}}) {
226 return $self->_error("No values in data series");
229 my @data = @{$self->_getDataSeries()->[0]->{'data'}};