Polygon Methods

The GD package includes a number of polygon manipulation routines that were not part of the original GD library, just to make life a little easier. All coordinate points are defined with (0, 0) being the upper left corner of the image and (image_width, image_height) being the lower right corner of the image.

The following example shows how you could use the GD::Polygonclass to implement a simple graphing program. The script takes any number of data sets (i.e., a list of y values representing a point on the graph) and writes out a multicolored graph with the area underneath each graph filled in with a different color (see Figure 4.5). The script is meant as a simple practical example of using polygons; note how the area and color of each polygon is managed with associative arrays, and how the polygons are sorted so that they can be plotted in a sensible order:

#!/usr/bin/perl -w
# 
# A polygon example that draws simple graphs.
#
use strict;
use GD;
my @polygons;                    # contains a polygon for each data set

my $max_x = 5;                   # The number of items in a data set
my $max_y = 100;                 # The maximum y value 
my $x_space = 40;                # Pixels between x values
my $width = $max_x * $x_space;   # The width of the image in pixels

# An array containing three data sets
#
my @data = ( [ 70, 85, 55, 45, 50 ] ,
         	    [ 25, 33, 22, 5, 40 ],
         	    [ 50, 67, 32, 24, 77 ]);
         
# Now generate a polygon for each data set by calling the 
# createDataSet() function. This funciton will return a 
# polygon object and the area of the bounding box of the polygon.
#
my %areas;
my ($poly, $area);
foreach my $dataset (@data) {
   ($poly, $area) = createDataSet($dataset);
   push @polygons, $poly;
   $areas{$poly} = $area; 
}

# Now create an image and allocate white as the background color
#
my $image = new GD::Image($width-$x_space, $max_y);
my $white = $image->colorAllocate(255, 255, 255);

# Now sort the polygons in order of decreasing area. We will 
# plot the graphs with the greatest bounding area first, on the 
# assumption that this will minimize the effect of one data set
# being obscured by another, since they will be drawn as filled polygons.
# Note that sorting by the bounding box alone does not guarantee
# that the graphs will be plotted in the right order, but
# it will work for most well-behaved data sets.
#
@polygons = reverse(sort { $areas{$a} <=> $areas{$b}; } @polygons);

# Now draw each polygon. First allocate a random color (note that this
# could be white or the same as another color).
#
my %color;            # keep track of the color index of each polygon
foreach my $poly (@polygons) {
    $color{$poly} = $image->colorAllocate(rand(255), rand(255), rand(255));
    $image->filledPolygon($poly, $color{$poly});
}

# Now go back and stroke each polygon with its color, in case it
# is obscured behind another polygon
#
map { 
    $image->polygon($_, $color{$_});
    } @polygons;

open O, ">graphout.gif";     # open a file
binmode O;
print O $image->gif;         # write the image as a GIF
close O;

sub createDataSet {
    # Take a reference to an array as an argument and return a
    # polygon object and the area of the polygon's bounding box.
    #
    my $dataset = shift;
    my $x = 0;
    my $poly = new GD::Polygon;
    foreach my $y (@$dataset) {
       # translate from origin at upper left corner to 
       # origin at lower left corner
       #
        $poly->addPt($x, $max_y - $y);    
        $x += $x_space;
    }

    # Close the polygon by adding the following points...
    #
    $poly->addPt($width, $max_y);       
    $poly->addPt(0, $max_y);
    my ($l, $r, $t, $b) = $poly->bounds;
    return ($poly, ($r-$l)*($b-$t));
}
A simple area graph using polygons drawn by the example script

Figure 4-5. A simple area graph using polygons drawn by the example script

In Chapter 6, we will look at the GIFgraph Perl module that accepts similar data sets but has a wide array of configurable options and graph output types.

Get Programming Web Graphics with Perl and GNU Softwar now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.