File Coverage

blib/lib/SVGGraph/Pie.pm
Criterion Covered Total %
statement 84 94 89.3
branch 25 32 78.1
condition n/a
subroutine 7 10 70.0
pod 0 2 0.0
total 116 138 84.0


line stmt bran cond sub pod time code
1             package SVGGraph::Pie;
2              
3 2     2   58290 use strict;
  2         5  
  2         80  
4 2     2   11 use vars qw($VERSION);
  2         4  
  2         295  
5             $VERSION = '0.06';
6 2     2   13 use constant PI => '3.141592654';
  2         9  
  2         176  
7 2     2   12 use constant GAP => 15;
  2         2  
  2         103  
8              
9 2     2   2612 use SVG;
  2         49112  
  2         14  
10              
11 0     0   0 sub _croak { require Carp; Carp::croak(@_) }
  0         0  
12 0     0   0 sub _carp { require Carp; Carp::carp(@_) }
  0         0  
13              
14             sub new {
15 1     1 0 13 my $self = shift;
16 1         5 return bless {}, $self;
17             }
18              
19             sub CreateGraph {
20 2     2 0 2966 my $self = shift;
21 2         4 my $options = shift;
22              
23             ## The rest are references to arrays of values, colors, lables
24 2         3 my $values = shift;
25              
26 2         4 my $start;
27             my @labelcolors;
28              
29             ## Option default settings
30 2         2 my $imageheight = 500;
31 2         2 my $imagewidth = 500;
32 2         3 my $radius = 180;
33 2 100       14 $imageheight = $$options{imageheight} if $$options{imageheight};
34 2 100       7 $imagewidth = $$options{imagewidth} if $$options{imagewidth};
35 2 100       9 $radius = $$options{radius} if $$options{radius};
36              
37 2         6 my $cx = int($imagewidth / 2) - 50;
38 2         4 my $cy = int($imageheight / 2);
39 2 100       8 $cx = $$options{centerleft} if $$options{centerleft};
40 2 100       7 $cy = $$options{centertop} if $$options{centertop};
41              
42 2         3 my $borderwidth = 4;
43 2 100       6 $borderwidth = $$options{borderwidth} if defined $$options{borderwidth};
44              
45             ## Calc total
46 2         2 my $total;
47 2         5 foreach (@$values) {
48 4         8 $total += $_->{value};
49             }
50              
51             ## Create SVG Object
52 2 100       22 my $svg = SVG->new(
53             width => $imageheight,
54             height => $imageheight,
55             title => ($$options{title} ? $$options{title} : ''),
56             );
57              
58             ## Draw Lines
59 2         606 $start = -90;
60              
61 2         3 my @separator_lines;
62 2         11 my $pie = $svg->tag('g', id => "pie_chart", transform => "translate($cx,$cy)");
63              
64 2         119 for (my $i = 0; $i < @$values; $i++) {
65 4         18 my $slice = $values->[$i]->{value} / $total * 360;
66              
67 4         7 my $color = $values->[$i]->{color};
68 4 50       10 if ($color eq "") {
69 0         0 $color = sprintf 'rgb(%d,%d,%d)',
70             int(rand(256)), int(rand(256)), int(rand(256));
71             }
72 4         5 push @labelcolors, $color;
73              
74 4         5 my $do_arc = 0;
75 4         7 my $radians = $slice * PI / 180;
76 4 100       9 $do_arc++ if $slice > 180;
77              
78 4         19 my $ry = ($radius * sin($radians));
79 4         20 my $rx = $radius * cos($radians);
80 4         7 push(@separator_lines, $rx, $ry, $start);
81              
82 4         16 my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate($start)");
83 4         265 $g->path(
84             style => {'fill' => "$color"},
85             d => "M $radius,0 A $radius,$radius 0 $do_arc,1 $rx,$ry L 0,0 z"
86             );
87              
88 4         156 $start += $slice;
89             }
90              
91             ## Draw circle
92 2         5 my $circlestyle = {'fill-opacity' => 0};
93 2 50       12 if ($borderwidth) {
94 2         21 $circlestyle->{stroke} = 'black';
95 2         4 $circlestyle->{'stroke-width'} = $borderwidth;
96             }
97              
98             $svg->circle(
99 2         118 cx => $cx,
100             cy => $cy,
101             r => $radius,
102             style => $circlestyle,
103             );
104              
105             ## Draw separater
106 2         95 my $i = 0;
107 2         5 while (my $start = pop(@separator_lines)) {
108 4         99 $i++;
109 4         5 my $separator_y = pop(@separator_lines);
110 4         5 my $separator_x = pop(@separator_lines);
111 4         15 my $g = $pie->tag('g', id => "line_$i", transform => "rotate($start)");
112 4         165 my $linestyle = {};
113 4 50       10 if ($borderwidth) {
114 4         6 $linestyle->{stroke} = 'black';
115 4         6 $linestyle->{'stroke-width'} = $borderwidth;
116             }
117              
118             $g->line(
119 4         11 x1 => 0,
120             y1 => 0,
121             x2 => $separator_x,
122             y2 => $separator_y,
123             style => $linestyle,
124             );
125             }
126              
127             ## Title
128 2 100       90 if ($$options{title}) {
129 1         2 my $titlestyle = 'font-size:24;';
130 1 50       3 $titlestyle = $$options{titlestyle} if $$options{titlestyle};
131 1         8 $svg->text(
132             'x' => 20,
133             'y' => 40,
134             'style' => $titlestyle,
135             )->cdata($$options{title});
136             }
137              
138             ## Label
139 2 50       80 if ($$options{label}) {
140 2         3 my $labelleft = $cx + $radius + 10;
141 2 50       4 $labelleft = $$options{labelleft} if $$options{labelleft};
142 2         3 $start = $cy - $radius;
143 2 50       5 $start = $$options{labeltop} if $$options{labeltop};
144              
145 2         4 for (my $i = 0; $i < @$values; $i++) {
146 4         19 $svg->rectangle(
147             'x' => $labelleft,
148             'y' => $start,
149             'width' => 20,
150             'height' => 20,
151             'rx' => 5,
152             'ry' => 5,
153             'style' => {
154             fill => $labelcolors[$i],
155             stroke => 'black',
156             },
157             );
158 4         223 $svg->text(
159             'x' => $labelleft + 25,
160             'y' => $start + GAP,
161             )->cdata($values->[$i]->{label});
162              
163 4         219 $start += 25;
164             }
165             }
166              
167 2         7 return $svg->xmlify;
168             }
169              
170             ## private method
171             sub _round {
172 0     0     my $decimal = shift;
173              
174 0           $decimal *= 10;
175 0           $decimal = int($decimal + 0.5);
176 0           $decimal /= 10;
177              
178 0           return $decimal;
179             }
180              
181             1;
182             __END__