########################################################################### # # GD::Gauge #========================================================================== # Copyright (c) 2002-2003 Christian Cloutier #-------------------------------------------------------------------------- # # Name: # GD::Gauge.pm # # Description: # Module to create gauges drawing on a GD::Image # object # #========================================================================== package GD::Gauge; require Exporter; require 5.000; use GD; use Math::Trig; our @ISA = qw(Exporter); our @EXPORT = qw(new gd imageAsPng imageAsJpeg); $GD::Gauge::VERSION = '0.1'; our $im; sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { @_ }; bless($self,$class); my ($brush,$arrow, %args); my ($white,$black,$red,$green,$blue,$yellow); my ($radius,$qtrrad,$value,$size,$percentred,$percentyellow,$clockwise,$tickvalue,$val); my ($pvalue,$pyellow,$pred,$pgreen, $side); my @big_ticks = qw(18 36 54 72 90 108 126 144 162); my @small_ticks = qw(9 27 45 63 81 99 117 135 153 171); %args = %$self; ($args{'size'} >= 100 && $args{'size'} <= 1000) ? ($size = $args{'size'}) : ($size = 150); ($args{'value'} <= 100 && $args{'value'} >= 0) ? ($value = $args{'value'}) : ($value = 0); ($args{'pyellow'} <= 100 && $args{'pyellow'} > 0) ? ($percentyellow = $args{'pyellow'}) : ($percentyellow = 10); ($args{'pred'} <= 100 && $args{'pred'} > 0) ? ($percentred = $args{'pred'}) : ($percentred = 5); ($args{'side'} == 0 || $args{'side'} == 1) ? ($side = $args{'side'}) : ($side = 0); if(($args{'pyellow'} + $args{'pred'}) > 100) { $args{'pred'} = 100 - $args{'pyellow'}; } $radius = $size / 2; $qtrrad = $radius * 0.74; $pyellow = ($percentyellow / 100) * 180; $pred = ($percentred / 100) * 180; $pgreen = (180 + $pred + $pyellow) / 2; $pvalue = ($value / 100) * 180; # Create the new image $im = new GD::Image($size,$size / 2 + 30); # Create arrow brush (2 x 2 pixels box) $brush = new GD::Image(2,2); $white = $brush->colorAllocate(255,255,255); $blue = $brush->colorAllocate(0,0,128); $brush->transparent($white); $brush->filledRectangle(0,0,2,2,$blue); $im->setBrush($brush); # Allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,30,30); $green = $im->colorAllocate(192,220,162); $blue = $im->colorAllocate(0,0,128); $yellow = $im->colorAllocate(255,255,120); # Make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Draw the gauge $im->line(0,$radius,$size - 1,$radius,$black); $im->arc($radius,$radius,$size,$size,180,360,$black); $im->arc($radius,$radius,$size - ($size * 0.25),$size - ($size * 0.25),180,360,$black); # Center circle $im->arc($radius,$radius,15,15,180,360,$black); $im->fillToBorder($radius, $radius - 3, $black, $black); if($side == 0) { # Red slice $im->line($radius - (cos(deg2rad($pred)) * $qtrrad),$radius - (sin(deg2rad($pred)) * $qtrrad), $radius - (cos(deg2rad($pred)) * $radius), $radius - (sin(deg2rad($pred)) * $radius), $black); $im->fill($radius - (cos(deg2rad($pred/2)) * ($radius * 0.8)), $radius - (sin(deg2rad($pred/2)) * ($radius * 0.8)), $red); # Yellow slice $im->line($radius - (cos(deg2rad($pred + $pyellow)) * $qtrrad),$radius - (sin(deg2rad($pred + $pyellow)) * $qtrrad), $radius - (cos(deg2rad($pred + $pyellow)) * $radius), $radius - (sin(deg2rad($pred + $pyellow)) * $radius), $black); $im->fill($radius - (cos(deg2rad($pred + $pyellow/2)) * ($radius * 0.8)), $radius - (sin(deg2rad($pred + $pyellow/2)) * ($radius * 0.8)), $yellow); # Green slice $im->fill($radius - (cos(deg2rad($pgreen)) * ($radius * 0.8)), $radius - (sin(deg2rad($pgreen)) * ($radius * 0.8)), $green); } else { # Red slice $im->line(cos(deg2rad($pred)) * $qtrrad + $radius,$radius - (sin(deg2rad($pred)) * $qtrrad), cos(deg2rad($pred)) * $radius + $radius, $radius - (sin(deg2rad($pred)) * $radius), $black); $im->fill(cos(deg2rad($pred/2)) * ($radius * 0.8) + $radius, $radius - (sin(deg2rad($pred/2)) * ($radius * 0.8)), $red); # Yellow slice $im->line(cos(deg2rad($pred + $pyellow)) * $qtrrad + $radius,$radius - (sin(deg2rad($pred + $pyellow)) * $qtrrad), cos(deg2rad($pred + $pyellow)) * $radius + $radius, $radius - (sin(deg2rad($pred + $pyellow)) * $radius), $black); $im->fill(cos(deg2rad($pred + $pyellow/2)) * ($radius * 0.8) + $radius, $radius - (sin(deg2rad($pred + $pyellow/2)) * ($radius * 0.8)), $yellow); # Green slice $im->fill(cos(deg2rad($pgreen)) * ($radius * 0.8) + $radius, $radius - (sin(deg2rad($pgreen)) * ($radius * 0.8)), $green); } # Draw tick marks $tickvalue = $radius - 8; foreach $val (@big_ticks) { $im->line($radius - (cos(deg2rad($val)) * $tickvalue), $radius - (sin(deg2rad($val)) * $tickvalue),$radius - (cos(deg2rad($val)) * $radius),$radius - (sin(deg2rad($val)) * $radius),$black); } $tickvalue = $radius - 5; foreach $val (@small_ticks) { $im->line($radius - (cos(deg2rad($val)) * $tickvalue), $radius - (sin(deg2rad($val)) * $tickvalue),$radius - (cos(deg2rad($val)) * $radius),$radius - (sin(deg2rad($val)) * $radius),$black); } # Value arrow $im->line($radius,$radius, $radius - (cos(deg2rad($pvalue)) * $radius), $radius - (sin(deg2rad($pvalue)) * $radius), gdBrushed); $arrow = new GD::Polygon; $arrow->addPt($radius - (cos(deg2rad($pvalue - 2)) * ($radius-10)), $radius - (sin(deg2rad($pvalue - 2)) * ($radius-10))); $arrow->addPt($radius - (cos(deg2rad($pvalue + 2)) * ($radius-10)), $radius - (sin(deg2rad($pvalue + 2)) * ($radius-10))); $arrow->addPt($radius - (cos(deg2rad($pvalue)) * $radius), $radius - (sin(deg2rad($pvalue)) * $radius)); $im->filledPolygon($arrow,$blue); # Title and other text $im->string(gdMediumBoldFont, $radius - 5, 0, "50", $black); $im->string(gdMediumBoldFont, 0, $radius, "0", $black); $im->string(gdMediumBoldFont, $size - 20, $radius, "100", $black); $im->string(gdGiantFont, $radius - 8, $radius - 30, $value, $blue); return $self,$class; } sub imageAsJpeg { return $im->jpeg if defined($im); } sub imageAsPng { return $im->png if defined($im); } sub gd { return $im if defined($im); } 1;