Subject: | Patch to improve SVG output for Pie charts |
The current version of SVGGraph::Pie (0.04) generates an SVG output which is around 120k in size and takes an inordinate amount of time to render in an SVG viewer. This patch reduces SVG output to around 4k and significantly reduces the render time.
-Brook
--- blib/lib/SVGGraph/Pie.pm Mon May 12 10:54:00 2003
+++ lib/SVGGraph/Pie.pm Sun Jul 27 21:33:11 2003
@@ -3,7 +3,7 @@
use strict;
use vars qw($VERSION);
$VERSION = '0.04';
-use constant PI => '3.14159265';
+use constant PI => '3.141592654';
use constant GAP => 15;
use SVG;
@@ -58,9 +58,13 @@
);
## Draw Lines
- $start = 0;
+ $start = -90;
+
+ my @separator_lines;
+ my $pie = $svg->tag('g', id => "pie_chart", transform => "translate($cx,$cy)");
+
for (my $i = 0; $i < @$values; $i++) {
- my $percent = _round($values->[$i]->{value} / $total * 100);
+ my $slice = $values->[$i]->{value} / $total * 360;
my $color = $values->[$i]->{color};
if ($color eq "") {
@@ -69,18 +73,29 @@
}
push @labelcolors, $color;
- for (my $j = $start; $j < $percent + $start; $j += 0.1) {
- $svg->line(
- x1 => $cx, y1 => $cy,
- x2 => $cx + sin(2 * PI * ($j / 100)) * $radius,
- y2 => $cy - cos(2 * PI * ($j / 100)) * $radius,
- style => {
- 'stroke' => $color,
- 'stroke-width' => $paintwidth,
- },
- );
- }
- $start += $percent;
+ my $do_arc = 0;
+ my $radians = $slice * PI / 180;
+ $do_arc++ if $slice > 180;
+
+ my $ry = ($radius * sin($radians));
+ my $rx = $radius * cos($radians);
+ push(@separator_lines, $rx, $ry, $start);
+
+ my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate($start)");
+ #my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate(-90)");
+ #my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate(-180)");
+ #my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate(180)");
+ #my $g = $pie->tag('g', id => "wedge_$i", transform => "rotate(90)");
+ #my $g = $pie->tag('g', id => "wedge_$i");
+
+ $g->path(style => { 'fill' => "$color",
+# 'stroke' => 'black',
+# 'stroke-width' => "$paintwidth",
+ },
+ d => "M $radius,0 A $radius,$radius 0 $do_arc,1 $rx,$ry L 0,0 z"
+ );
+
+ $start += $slice;
}
## Draw circle
@@ -96,21 +111,22 @@
);
## Draw separater
- $start = 0;
- for (my $i = 0; $i < @$values; $i++) {
- my $percent = _round($values->[$i]->{value} / $total * 100);
-
- $svg->line(
- x1 => $cx,
- y1 => $cy,
- x2 => $cx + sin(2 * PI * ($start / 100)) * $radius,
- y2 => $cy - cos(2 * PI * ($start / 100)) * $radius,
+ my $i = 0;
+ while (my $start = pop(@separator_lines)) {
+ $i++;
+ $cy = pop(@separator_lines);
+ $cx = pop(@separator_lines);
+ my $g = $pie->tag('g', id => "line_$i", transform => "rotate($start)");
+ $g->line(
+ x1 => 0,
+ y1 => 0,
+ x2 => $cx,
+ y2 => $cy,
style => {
'stroke' => 'black',
'stroke-width' => $borderwidth
},
);
- $start += $percent;
}
## Title
@@ -135,16 +151,17 @@
$svg->rectangle(
'x' => $labelleft,
'y' => $start,
- 'width' => 40,
+ 'width' => 20,
'height' => 20,
'rx' => 5,
'ry' => 5,
'style' => {
fill => $labelcolors[$i],
+ stroke => 'black',
},
);
$svg->text(
- 'x' => $labelleft + 45,
+ 'x' => $labelleft + 25,
'y' => $start + GAP,
)->cdata($values->[$i]->{label});