Chart-ThreeD

 view release on metacpan or  search on metacpan

lib/Chart/ThreeD/Pie.pm  view on Meta::CPAN


    # make sure we are writing to a binary stream
    binmode STDOUT;

    # Draw the pie, Convert the image to GIF and print it on standard output
    print $pie->plot->gif;

=head1 DESCRIPTION

    Chart::ThreeD::Pie allows you to create 3D Piecharts very easily
    and emit the drawings as GIF files. You can customize almost everything
    using a large number of methods.

    This module requires the Lincoln D. Stein's GD module available on CPAN.

=head1 Method Calls


=head2 Creating Pie

=over 5

=item C<new>

C<Chart::ThreeD::Pie::new(width, height, title)> I<class method>

To create a new pie, send a new() message to the Chart::ThreeD::Pie
class.  For example:

        $pie = new Chart::ThreeD::Pie (450, 320, 'my title');

This will create an image that is 450 x 320 pixels wide.  If you don't
specify the dimensions, a default of 400 x 300 will be chosen. The default
title is an empty string (no title). The three parameters can be changed
using the corresponding methods specified bellow.

=back

=cut

# A new Pie object
sub new {
  my $this = shift;
  my $class = ref($this) || $this;
  my $self = {};
  bless $self, $class;
  $self->initialize (@_);
  return $self;
}

sub initialize {
  my $self = shift;

  $self->{xmax}  = shift || 400;
  $self->{ymax}  = shift || 300;
  $self->{title} = shift || '';
  $self->{data}  = [];
  $self->{bgcolor} = '#FFFFFF';
  $self->{fgcolor} = '#000000';
  $self->{limit} = [ 7, '#FF0000', 'others' ];
  $self->{transparent} = 0;
  $self->{interlaced} = 0;
  $self->{thickness} = 30; # pixels
  $self->{radius} = $self->{xmax} / 3;
  $self->{want_sort} = 0;
  $self->{border} = 0;
  $self->{percents} = 0;
}

=head2 Commands

=over 5

=item C<thickness>

C<Chart::ThreeD::Pie::thickness(val)> I<object method>

This allows you to set the thickness (in pixel) of the pie if val is
defined. The current value is returned. Default value is 30 pixels.

Example:

      print "Current thickness is ", $pie->thickness, " pixels\n";
      # set it to 20.
      $pie->thickness(20);

=cut

sub thickness {
  my $self = shift;
  my $arg  = shift;
  $self->{thickness} = $arg if defined $arg;
  return $self->{thickness};
}

=item C<want_sort>

C<Chart::ThreeD::Pie::thickness(bool)> I<object method>

This will allow you to sort the parts of the pie if bool is non-null.
The current value is returned. Default is null;

Example:

      print "Current want_sort value is ", $pie->want_sort, "\n";
      # set it to true
      $pie->want_sort(1);

=cut

sub want_sort {
  my $self = shift;
  my $arg  = shift;
  $self->{want_sort} = $arg if defined $arg;
  return $self->{want_sort};
}

=item C<transparent>

C<Chart::ThreeD::Pie::transparent(bool)> I<object method>

This will allow you to make the background of the final picture transparent
if bool is non-null. The current value is returned. Default is null;

Example:

      # Background will be transparent.
      $pie->transparent(1);

=cut

sub transparent {
  my $self = shift;
  my $arg  = shift;
  $self->{transparent} = $arg if defined $arg;
  return $self->{transparent};
}

=item C<interlaced>

C<Chart::ThreeD::Pie::interlaced(bool)> I<object method>

This will allow you to make the background of the final picture interlaced
if bool is non-null. The current value is returned. Default is null;

Example:

      # Picture will be interlaced
      $pie->interlaced(1);

=cut

sub interlaced {
  my $self = shift;
  my $arg  = shift;
  $self->{interlaced} = $arg if defined $arg;
  return $self->{interlaced};
}

=item C<percents>

C<Chart::ThreeD::Pie::percents(bool)> I<object method>

This will add percentages after the label of each part of the pie
if bool is non-null. The current value is returned. Default is null;

Example:

      # add percents in labels
      $pie->percents(1);

=cut

sub percents {
  my $self = shift;
  my $arg  = shift;
  $self->{percents} = $arg if defined $arg;
  return $self->{percents};
}

=item C<bgcolor>

C<Chart::ThreeD::Pie::bgcolor(bgcolor)> I<object method>

Set the background color if bgcolor is defined. The current value is
returned. Default value is '#000000' (black). Color is a string
composed of a '#' followed by 3 two-digits hexadecimal values, respectively
Red, Green and Blue.

Example:

      # set the background color to yellow
      $pie->bgcolor ('#FFFF00');

=cut

lib/Chart/ThreeD/Pie.pm  view on Meta::CPAN

  return $self->{ymax};
}

=item C<title>

C<Chart::ThreeD::Pie::title(val)> I<object method>

This allows you to change the title of the pie if val is defined.
The current value is returned.

Example:

      print "Current title is '", $pie->title, "'\n";
      # set it to 'my own title'.
      $pie->title('my own title');

=cut

sub title {
  my $self = shift;
  my $arg  = shift;
  $self->{title} = $arg if defined $arg;
  return $self->{title};
}

=item C<add>

C<Chart::ThreeD::Pie::add(val, color, label)> I<object method>

This method adds a part to a pie. The size of the part is specified by val.
Both color and label are optional. The default color is '#DDDDDD' and the
default label is ''.

=cut

sub add {
  my $self  = shift;
  my $value = shift;
  my $color = shift || "#DDDDDD";
  my $label = shift || '';
  push @{$self->{data}}, [ $value, $color, $label ];
}

=item C<plot>

C<Chart::ThreeD::Pie::plot()> I<object method>

Draw the pie. This method returns a GD object (see L<GD>).

=cut

sub plot {
  my $self = shift;

  my $pie = new GD::Image($self->xmax, $self->ymax);

  my $fontw = gdSmallFont->width;
  my $fonth = gdSmallFont->height;

  my $bgcolor = $pie->colorAllocate (&cvtcolor ($self->bgcolor));
  $pie->transparent ($bgcolor) if $self->transparent;
  $pie->fill (0, 0, $bgcolor);
  my $total = 0;
  map { $total += $$_[0] } @{$self->{data}};

  my $fgcolor = $pie->colorAllocate (&cvtcolor ($self->fgcolor));
  my $defaultcolor = $pie->colorAllocate (&cvtcolor (${$self->limit}[1]));
  my $defaultcolor2 = $pie->colorAllocate
    (&shadecolor (&cvtcolor (${$self->limit}[1])));

  my $orgx = $self->xmax / 2;
  my $orgy = $self->ymax / 2 - $self->thickness / 2 + gdGiantFont->height / 2;

  my $x = $self->radius * 11 / 6;
  my $y = $self->radius * 7 / 6;
  $pie->arc ($orgx, $orgy, $x, $y, 0, 360, $fgcolor);
  $pie->fill ($orgx, $orgy, $defaultcolor);
  $pie->arc ($orgx, $orgy + $self->thickness, $x, $y, 0, 180, $fgcolor);
  $pie->line ($orgx - $x / 2, $orgy, $orgx - $x / 2, $orgy + $self->thickness,
	      $fgcolor);
  $pie->line ($orgx + $x / 2, $orgy, $orgx + $x / 2, $orgy + $self->thickness,
	      $fgcolor);
  $pie->fill ($orgx, $orgy + $self->thickness * 3 / 4 + $y / 2,
	      $defaultcolor2);

  my @data = $self->want_sort ? sort {$$b[0] <=> $$a[0]} @{$self->{data}} :
    @{$self->{data}};
  my ($elem, $old);
  my $num = 0;
  my $a0 = 270;
  my $a = $a0;
  my $k = 0.55;
  for $elem (@data) {
    $num++;
    my $angle = 360 * $$elem[0] / $total;
    my $ang   = $a + $angle / 2;
    my $h = sin (&deg2rad ($ang - $a0));
    my $r = cos (&deg2rad ($ang - $a0));

    my $color = $pie->colorAllocate (&cvtcolor ($$elem[1]));
    my $color2 = $pie->colorAllocate (&shadecolor (&cvtcolor ($$elem[1])));

    my $dial = 0;
    $dial = 1 if $h >= 0 && $r >= 0;
    $dial = 2 if $h >= 0 && $r <  0;
    $dial = 3 if $h <  0 && $r <  0;
    $dial = 4 if $h <  0 && $r >= 0;
    if (!$self->want_sort || !${$self->limit}[0] ||
	($ {$self->limit}[0] > 0 && $angle > $ {$self->limit}[0] * 3.6)) {
      $pie->line ($orgx, $orgy, $orgx - $x / 2 * sin (&deg2rad ($a)),
		  $orgy - $y / 2 * cos (&deg2rad ($a)), $fgcolor)
	unless $$elem[0] == $total;

      $pie->line ($orgx, $orgy,
		  $orgx - $x / 2 * sin (&deg2rad ($a + $angle)),
		  $orgy - $y / 2 * cos (&deg2rad ($a + $angle)), $fgcolor)
	unless $$elem[0] == $total;
      $pie->fill ($orgx - $x / 4 * sin (&deg2rad ($a + $angle / 2)),
		  $orgy - $y / 4 * cos (&deg2rad ($a + $angle / 2)),
		  $color);
      $pie->line ($orgx - $x / 2 * sin (&deg2rad ($a + $angle)),



( run in 1.262 second using v1.01-cache-2.11-cpan-39bf76dae61 )