Annotation of loncom/cgi/plot.gif, revision 1.1

1.1     ! matthew     1: #!/usr/bin/perl 
        !             2: #
        !             3: # $Id$
        !             4: #
        !             5: # Copyright Michigan State University Board of Trustees
        !             6: #
        !             7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
        !             8: #
        !             9: # LON-CAPA is free software; you can redistribute it and/or modify
        !            10: # it under the terms of the GNU General Public License as published by
        !            11: # the Free Software Foundation; either version 2 of the License, or
        !            12: # (at your option) any later version.
        !            13: #
        !            14: # LON-CAPA is distributed in the hope that it will be useful,
        !            15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            17: # GNU General Public License for more details.
        !            18: #
        !            19: # You should have received a copy of the GNU General Public License
        !            20: # along with LON-CAPA; if not, write to the Free Software
        !            21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !            22: #
        !            23: # /home/httpd/cgi-bin/plot.gif
        !            24: #
        !            25: # http://www.lon-capa.org/
        !            26: #
        !            27: # CGI-BIN interface to GD, used for making mathematical plots.
        !            28: #
        !            29: # User specifies the following variables (given are defaults):
        !            30: #    height   = "100"
        !            31: #    width    = "100"
        !            32: #    xmin     = "-10.0"
        !            33: #    xmax     = " 10.0"
        !            34: #    ymin     = "-10.0"
        !            35: #    ymax     = " 10.0"
        !            36: #    frame    
        !            37: #    drawaxes 
        !            38: #    drawtics 
        !            39: #    vtic_every = "1.0"
        !            40: #    htic_every = "1.0"
        !            41: #    xseries1  = "x1,x2,x3,x4,x5,...,xn"
        !            42: #    yseries1  = "y1,y2,y3,y4,y5,...,yn"
        !            43: #    xseries2  = ..
        !            44: #    yseries2  = ..
        !            45: #    ...
        !            46: #    label1 = "x,y,size,text"
        !            47: #    label2 = "x,y,size,text"
        !            48: #    label3 = "x,y,size,text"
        !            49: #    ...
        !            50: #
        !            51: #    size of a labelN is one of :
        !            52: #       giant, large, medium, small, tiny
        !            53: #
        !            54: use GD;
        !            55: 
        !            56: my @inputs = split(/&/,$ENV{'QUERY_STRING'});
        !            57: foreach $input (@inputs) {
        !            58:     ($var,$val) = split /\=/,$input,2;
        !            59:     if (! defined($val)) {
        !            60: 	$val = 1;
        !            61:     }
        !            62:     $In{lc($var)}=$val;
        !            63: }
        !            64: 
        !            65: $height = &grab('height',100,\%In);
        !            66: $width  = &grab('width',100,\%In);
        !            67: $axis->{'xmin'} = &grab('xmin',-10,\%In);
        !            68: $axis->{'xmax'} = &grab('xmax', 10,\%In);
        !            69: $axis->{'ymin'} = &grab('ymin',-10,\%In);
        !            70: $axis->{'ymax'} = &grab('ymax', 10,\%In);
        !            71: $axis->{'xlen'} = $axis->{'xmax'} - $axis->{'xmin'};
        !            72: $axis->{'ylen'} = $axis->{'ymax'} - $axis->{'ymin'};
        !            73: $vtic_every = &grab('vtic_every',1.0,\%In);
        !            74: $htic_every = &grab('htic_every',1.0,\%In);
        !            75: 
        !            76: my $image = new GD::Image($height,$width);
        !            77: 
        !            78: # allocate standard colors
        !            79: my $white = $image->colorAllocate(255,255,255);
        !            80: my $black = $image->colorAllocate(  0,  0,  0);       
        !            81: 
        !            82: # Draw a black frame around the picture
        !            83: &drawtics($htic_every,$vtic_every) if (exists($In{"drawtics"}));
        !            84: &drawaxes($axis)                   if (exists($In{"drawaxis"}));
        !            85: &frame(1)                          if (exists($In{'frame'}));
        !            86: 
        !            87: ## Take care of labels and data series
        !            88: foreach (keys %In) {
        !            89:     if (/^label/) {
        !            90: 	my ($x,$y,$size,$text) = split/,/,$In{$_};
        !            91: 	&drawstring($text,$x,$y,$black,$size);
        !            92: 	delete ($In{$_});
        !            93: 	next;
        !            94:     } elsif (/^xseries/) {
        !            95: 	$xname = $_;
        !            96: 	$yname = $xname;
        !            97: 	$yname =~ s/^x/y/;
        !            98: 	(@X)=split/,/,$In{$xname};
        !            99: 	(@Y)=split/,/,$In{$yname};
        !           100: 	delete ($In{$xname});
        !           101: 	delete ($In{$yname});	
        !           102: 	if ($#X != $#Y) {
        !           103: 	    &drawstring("size of $xname and $yname do not match",
        !           104: 		       10,10,$black,"giant");
        !           105: 	    next;
        !           106: 	}
        !           107: 	&drawcurve(\@X,\@Y);
        !           108:     }
        !           109: }
        !           110: 
        !           111: # make the background transparent and interlaced
        !           112: $image->transparent($white);
        !           113: 
        !           114: # make sure we are writing to a binary stream
        !           115: binmode STDOUT;
        !           116: 
        !           117: # Convert the image to PNG and print it on standard output
        !           118: print <<END;
        !           119: Content-type: image/png
        !           120: 
        !           121: END
        !           122: 
        !           123: my $BinaryData=$image->plot(\@data)->png;
        !           124: undef $image;
        !           125: binmode(STDOUT);
        !           126: open IMG,"|pngtopnm|ppmtogif 2>/dev/null"; # convert into a gif image
        !           127: print IMG $BinaryData; # output image
        !           128: $|=1;                  # be sure to flush before closing
        !           129: close IMG;
        !           130: 
        !           131: 
        !           132: #--------------------------------------------------------------------
        !           133: 
        !           134: sub grab{
        !           135:     my ($name,$default,$h) = @_;
        !           136:     my $value = $h->{$name};
        !           137:     if (defined($value)) {
        !           138: 	delete ($h->{$name}) ;
        !           139:     } else {
        !           140: 	$value = $default;
        !           141:     }
        !           142:     return $value;
        !           143: }
        !           144: 
        !           145: # transformPoint(x,y) where x,y are in the coordinates of axis will return
        !           146: # the coordinates transformed to the image coordinate system.
        !           147: sub transformPoint{
        !           148:     my ($x,$y) = @_;
        !           149:     my ($width,$height) = $image->getBounds();
        !           150:     $x = ( $x - $axis->{"xmin"}) * $width / ( $axis->{"xlen"});
        !           151:     $y = ( ( $axis->{"ylen"} ) - ($y - $axis->{"ymin"})) 
        !           152: 	* $height / ( $axis->{"ylen"} );
        !           153:     return($x,$y);
        !           154: }
        !           155: 
        !           156: sub drawaxes{
        !           157:     ($x1,$y1) = &transformPoint($axis->{"xmin"},0,$image,$axis);
        !           158:     ($x2,$y2) = &transformPoint($axis->{"xmax"},0,$image,$axis);
        !           159:     $image->line($x1,$y1,$x2,$y2,$black);
        !           160:     ($x1,$y1) = &transformPoint(0,$axis->{"ymin"},$image,$axis);
        !           161:     ($x2,$y2) = &transformPoint(0,$axis->{"ymax"},$image,$axis);
        !           162:     $image->line($x1,$y1,$x2,$y2,$black);
        !           163: }
        !           164: 
        !           165: sub drawtics{
        !           166:     my ($htic_every,$vtic_every) = @_;
        !           167:     my ($width,$height) = $image->getBounds();
        !           168:     
        !           169:     $ticwidth  = ($width  > 99 ? 10 : int($width /10) + 1);
        !           170:     $ticheight = ($height > 99 ? 10 : int($height/10));
        !           171: 
        !           172:     # Do tics along y-axis
        !           173:     for ($ntic = 0; $ntic <=int($axis->{"ylen"}/$vtic_every); $ntic++){
        !           174: 	my ($x1,$y1) = &transformPoint(0,$axis->{"ymin"}+$ntic*$vtic_every);
        !           175: 	my ($x2,$y2) = &transformPoint(0,$axis->{"ymin"}+$ntic*$vtic_every);
        !           176: 	$x1 -= $ticwidth;
        !           177: 	$x2 += $ticwidth;
        !           178: 	$image->line($x1,$y1,$x2,$y2,$black);
        !           179:     }
        !           180:     # Do tics along x-axis
        !           181:     for ($ntic = 0; $ntic <=int($axis->{"xlen"}/$htic_every); $ntic++){
        !           182: 	my ($x1,$y1) = &transformPoint( $axis->{"xmin"}+$ntic*$htic_every,0);
        !           183: 	my ($x2,$y2) = &transformPoint( $axis->{"xmin"}+$ntic*$htic_every,0);
        !           184: 	$y1 -= $ticheight;
        !           185: 	$y2 += $ticheight;
        !           186: 	$image->line($x1,$y1,$x2,$y2,$black);
        !           187:     }
        !           188: }
        !           189: 
        !           190: sub drawcurve{
        !           191:     my ($X,$Y) = @_;
        !           192:     for($i=0;$i< (@$X-1);$i++) {
        !           193: 	($x1,$y1) = &transformPoint($X->[$i  ],$Y->[$i  ]);
        !           194: 	($x2,$y2) = &transformPoint($X->[$i+1],$Y->[$i+1]);
        !           195: 	$image->line($x1,$y1,$x2,$y2,$black);
        !           196:     }
        !           197: }
        !           198: 
        !           199: sub frame{
        !           200:     # Draw a frame around the picture.
        !           201:     my ($xoffset,$yoffset) = @_;
        !           202:     $xoffset = $xoffset || 1;
        !           203:     $yoffset = $yoffset || $xoffset;
        !           204:     my ($width,$height) = $image->getBounds();
        !           205:     $image->rectangle($xoffset-1,$yoffset-1,$width-$xoffset,$height-$yoffset,$black);
        !           206: }
        !           207: 
        !           208: sub drawstring{
        !           209:     # Write some text on the image.
        !           210:     my ($text,$x,$y,$color,$fontName) = @_;
        !           211:     $font = gdGiantFont      if (lc($fontName) eq "giant" ||
        !           212: 				 lc($fontName) eq "huge"     );
        !           213:     $font = gdLargeFont      if (lc($fontName) eq "large");
        !           214:     $font = gdMediumBoldFont if (lc($fontName) eq "medium");
        !           215:     $font = gdSmallFont      if (lc($fontName) eq "small");
        !           216:     $font = gdTinyFont       if (lc($fontName) eq "tiny");
        !           217:     if (! defined($font)) {
        !           218: 	$font = gdGiantFont;
        !           219: 	$text = "Font size error!";
        !           220:     }
        !           221:     ($x,$y) = &transformPoint($x,$y);
        !           222:     $image->string($font,$x,$y,$text,$color);
        !           223: }
        !           224: 
        !           225: 
        !           226: 
        !           227: 
        !           228: 
        !           229: 
        !           230: 
        !           231: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>