Perl Cairo tutorial - Pie chart

This is one page of a Perl Cairo tutorial.

This example draws a pie chart. It demonstrates arc.
#!/home/ben/software/install/bin/perl
use warnings;
use strict;
use Cairo;
use constant {
    M_PI => 3.14159265,
};
my $size = 500;
my $surface = Cairo::ImageSurface->create ('argb32', $size, $size);
my $cr = Cairo::Context->create ($surface);
$cr->rectangle (0, 0, $size, $size);
$cr->set_source_rgb (1, 1, 1);
$cr->fill ();

my @sales = <DATA>;
# Sales by country.
my %countries;
my @ranks;
for my $country (@sales) {
    if (! $country) {
        next;
    }
    my (undef, $rank2012, $rank2011, $country, $sales, undef) =
        split /,/, $country; 
    if (! $sales) {
        next;
    }
    $countries{$country}{sales} = $sales;
    if ($country ne 'Total') {
        push @ranks, $country;
    }
}
my $total = $countries{Total}{sales};
for my $country (@ranks) {
    $countries{$country}{fraction} = $countries{$country}{sales} / $total;
}
my $to_angle = M_PI * 3 / 2;
my $from_angle = $to_angle;
my $count;
for my $country (@ranks) {
    $to_angle += 2 * M_PI * $countries{$country}{fraction};
    $cr->set_source_rgb (lightcolour ());
#    print "$from_angle $to_angle\n";
    $count++;
#    last if $count > 10;
    $cr->move_to ($size/2, $size/2);
    $cr->arc ($size/2, $size/2, $size*.45, $from_angle, $to_angle);
    $cr->line_to ($size/2, $size/2);
    $cr->fill ();
    $from_angle = $to_angle;
}
$cr->set_font_size ($size/30);
$to_angle = M_PI * 3 / 2;
$from_angle = $to_angle;
for my $country (@ranks) {
    if ($countries{$country}{fraction} < 0.01) {
        next;
    }
    $to_angle += 2 * M_PI * $countries{$country}{fraction};
    my $label_angle = ($from_angle + $to_angle) / 2;
    my $label_x = $size/2 * (1 + 0.7 * cos ($label_angle));
    my $label_y = $size/2 * (1 + 0.7 * sin ($label_angle));
    $cr->set_source_rgb (0, 0, 0);
    $cr->move_to ($label_x, $label_y);
    $cr->show_text ($country);
    $cr->fill ();
    $from_angle = $to_angle;
}

$surface->write_to_png ('pie-chart.png');
exit;

sub lightcolour
{
    my @colours;
    for (1..3) {
        push @colours, 0.5 + 0.5 * rand ();
    }
    return @colours;
}

# "TIV of arms exports from the top 50 largest exporters, 2012-2012",,,,,
# Generated: 05 January 2014,,,,,
# Figures are SIPRI Trend Indicator Values (TIVs) expressed in US$ m. at constant (1990) prices.,,,,,
# Figures may not add up due to the conventions of rounding.,,,,,
# A '0' indicates that the value of deliveries is less than US$0.5m,,,,,
# "For more information, see http://www.sipri.org/databases/armstransfers/background",,,,,

__DATA__
,1,1,USA,8760,8760
,2,2,Russia,8003,8003
,3,4,China,1783,1783
,4,11,Ukraine,1344,1344
,5,6,Germany (FRG),1193,1193
,6,3,France,1139,1139
,7,7,UK,863,863
,8,8,Italy,847,847
,9,10,Netherlands,760,760
,10,5,Spain,720,720
,11,12,Israel,533,533
,12,9,Sweden,496,496
,13,13,Canada,276,276
,14,14,Switzerland,210,210
,15,15,South Korea,183,183
,16,17,Norway,169,169
,17,21,South Africa,145,145
,18,34,Poland,140,140
,19,42,Romania,108,108
,20,31,Singapore,76,76
,21,,New Zealand,75,75
,22,18,Australia,75,75
,23,27,Finland,62,62
,24,25,Turkey,53,53
,25,24,Brazil,32,32
,26,40,Ireland,25,25
,27,29,Denmark,23,23
,28,19,Belgium,21,21
,29,43,Unknown country,16,16
,30,,Jordan,12,12
,31,26,Austria,9,9
,32,33,Czech Republic,8,8
,33,,Botswana,4,4
,34,39,Bulgaria,3,3
,35,,Taiwan,2,2
,36,35,India,2,2
,37,36,Serbia,1,1
,38,20,Iran,0,0
,39,45,Portugal,0,0
,40,32,Moldova,,
,41,22,Belarus,,
,42,41,Argentina,,
,43,16,Uzbekistan,,
,44,30,Bosnia-Herzegovina,,
,45,44,Albania,,
,46,23,Saudi Arabia,,
,47,28,Brunei,,
,48,37,Indonesia,,
,49,38,UAE,,
,,,,,
,,,Others,,
,,,Total,28172,28172

(download)


Copyright © Ben Bullock 2009-2023. All rights reserved. For comments, questions, and corrections, please email Ben Bullock (benkasminbullock@gmail.com) or use the discussion group at Google Groups. / Privacy / Disclaimer