Location: PHPKode > projects > Weathermap5rrd > weathermap5rrd-1.3.11/lib/graphic.php
<?php
/*
 * weathermap5rrd - graphic.php
 * Copyright (C) 2008 Zdenek Styblik
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Authors:
 * Zdenek Styblik ~ 2007-2008
 * Alexandre Fontelle ~ 2005-2006
 *
 * This script is a modified version of graphic.php 
 * of Cacti project (http://www.cacti.net)
 *
 */
class graphic
{
	public $black = -1;
	public $darkgray = -1;
	public $gray = -1;
	public $green = -1;
	public $orange = -1;
	public $red = -1;
	public $white = -1;
	public $font = 3;
	// ready-up
	function __construct()
 	{
	}
	// clean-up
	function __destruct()
 	{
		unset($this->black);
		unset($this->darkgray);
		unset($this->gray);
		unset($this->green);
		unset($this->orange);
		unset($this->red);
		unset($this->white);
	}
	# @return: color;
	public function getBlack()
 	{
		return $this->black;
	}
	# @return: color;
	public function getGreen()
 	{
		return $this->green;
	}
	# @return: color;
	public function getRed()
 	{
		return $this->red;
	}
	# @return: color;
	public function getWhite()
 	{
		return $this->white;
	}
	# $fontsize: int;
	# @return: void;
	public function setFont($fontsize = null)
 	{
		if (!is_null($fontsize) && is_numeric($fontsize))
		{
			$this->font = $fontsize;
			return 0;
		}
		else
		{
			return 1;
		}
	}

	public function setColors($black = -1, $darkgray = -1, $gray = -1, $orange = -1,
	 	$red = -1, $white = -1)
 	{
		if (is_numeric($black) && is_numeric($red) && is_numeric($white)
			&& is_numeric($orange) && is_numeric($gray) && is_numeric($darkgray))
	 	{
			$this->black = $black;
			$this->darkgray = $darkgray;
			$this->gray = $gray;
			$this->orange = $orange;
			$this->red = $red;
			$this->white = $white;
			return 0;
		}
		else
	 	{
			return 1;
		} /* not is_numeric */
	}

	public function middle($x1, $x2)
 	{
		$retval = $x1+($x2-$x1)/2;
		/* point in the middle correction
		 * aka Neat bug, Jimbo!
		 */
		$retval+= 0.00000001;
		return $retval;
	}

	public function dist($x1, $x2)
 	{
		$retval = sqrt($x1*$x1+$x2*$x2);
		return $retval;
	}

	public function dist_bw_points($x1, $y1, $x2, $y2)
 	{
		$x1=round($x1);
		$x2=round($x2);
		$y1=round($y1);
		$y2=round($y2);
		$retval = sqrt(($x2-$x1)*($x2-$x1)+($y2-$y1)*($y2-$y1));
		return $retval;
	}

	public function newx ($a, $b, $x, $y)
	{
		$retval = cos(atan2($y,$x)+atan2($b,$a))*sqrt($x*$x+$y*$y);
		/* point in the middle correction
		 * aka Neat bug, Jimbo!
		 */
		$retval+= 0.00000001;
		return $retval;
	}

	public function newy ($a, $b, $x, $y)
 	{
		$retval = sin(atan2($y,$x) + atan2($b,$a)) * sqrt($x*$x + $y*$y);
		/* point in the middle correction
		 * aka Neat bug, Jimbo!
		 */
		$retval+= 0.00000001;
		return $retval;
	}
	public function getposy_line($x, $x1, $y1, $x2, $y2)
 	{
		if (($x2-$x1) == 0)
			$x2+= 1;
		$a=($y2-$y1)/($x2-$x1);
		$b=$y1-$a*$x1;
		$retval = $a*$x+$b;
		return $retval;
	}
	# @return: int;
	public function getposx_line($y, $x1, $y1, $x2, $y2)
 	{
		if (($y2 - $y1) == 0)
			$y2+= 1;
		$c=($x2-$x1)/($y2-$y1);
		$d=$x1-$c*$y1;
		$retval = $c*$y+$d;
		return $retval;
	}
	# @return: array();
	public function get_gd_ver()
 	{
		ob_start();
		phpinfo(8);
		$info = ob_get_contents();
		ob_end_clean();
		$info = stristr($info, 'gd version');
		preg_match('/\d(\.\d{0,}){0,}/', $info, $match);
		$gd_ver = $match[0];
		preg_match('/(\d{0,2})\.{0,1}(\d{0,2})\.{0,1}(\d{0,2})/', $gd_ver, $match);
		$gd_version[0] = $gd_ver;
		$gd_version[1] = $match[1];
		$gd_version[2] = $match[2];
		$gd_version[3] = $match[3];
		return $gd_version;
	}
	# @return: image;
	public function draw_arrow($im, $x1, $y1, $x2, $y2, $w, $solid, $color)
 	{
		$point[0] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, $w);
		$point[1] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, $w);
		$point[2] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[3] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[6] = $x2;
		$point[7] = $y2;
		$point[8] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[9] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[10] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[11] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[12] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[13] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		# allocate black color
		if ($this->black == -1)
			$this->define_colors($im);
		if ($solid == 1)
	 	{
			imagefilledpolygon($im, $point, 7, $color);
			imagepolygon($im, $point, 7, $this->black);
		}
		else
	 	{
			imagepolygon($im, $point, 7, $this->black);
		} /* not $solid */
		return $im;
	}
	# return: image;
	public function draw_arrow_half($im, $x1, $y1, $x2, $y2, $w, $solid, $color)
 	{
		$point[0] = $x1;
		$point[1] = $y1; 
		$point[2] = $x2;
		$point[3] = $y2;
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, -6*$w, -3*$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, -6*$w, -3*$w);
		$point[6] = $x2 + $this->newx($x2-$x1, $y2-$y1, -6*$w, -$w);
		$point[7] = $y2 + $this->newy($x2-$x1, $y2-$y1, -6*$w, -$w);
		$point[8] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[9] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		if ($this->black == -1)
			$this->define_colors($im);
		if ($solid == 1)
	 	{
			imagefilledPolygon($im, $point, 5, $color);
			imagepolygon($im, $point, 5, $this->black);
		}
		else
	 	{
			imagepolygon($im, $point, 5, $this->black);
		} /* not $solid */
		return $im;
	}

	public function draw_arrow_circle3($im, $x1, $y1, $x2, $y2, $w, $step, $solid, $color)
 	{
		$dif_horizontal = abs($x1-$x2);
		$dif_vertical = abs($y1-$y2);
		$gd_ver = $this->get_gd_ver();
		if ($dif_horizontal > $dif_vertical)
	 	{
			if ($x1 < $x2)
		 	{
				$yi = $this->getposy_line($x1, $x1, $y1, $x2, $y2);
				for ($xi = $x1; $this->dist_bw_points($xi, $yi, $x2, $y2) > 4*$w; $xi = $xi+2*$w+$step)
			 	{
					$yi = $this->getposy_line($xi, $x1, $y1, $x2, $y2);
					# note: GD back-compatability?
					if ($solid && $gd_ver[1] >= 2)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* not $solid */
					if ($solid && $gd_ver[1] < 2)
						imagearc($im, $xi, $yi, 2*$w+2, 2*$w+2, 0, 360, $color);
				} /* for $xi = $x1 */
			}
			else
		 	{
				$yi = $this->getposy_line($x1, $x1, $y1, $x2, $y2);
				for ($xi = $x1; $this->dist_bw_points($xi,$yi,$x2,$y2) > 4*$w; $xi = $xi-2*$w-$step)
			 	{
					$yi = $this->getposy_line($xi, $x1, $y1, $x2, $y2);
					if ($solid && $gd_ver[1] >= 2)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} // if $solid
					if ($solid && $gd_ver[1] < 2)
						imagearc($im, $xi, $yi, 2*$w+2, 2*$w+2, 0, 360, $color);
				} /* for $x1 = $x1 */
			} /* not $x1 < $x2 */
		}
		else
	 	{
			if ($y1 < $y2) {
				$xi = $this->getposx_line($y1+$w, $x1, $y1, $x2, $y2);
				for ($yi = $y1+$w; $this->dist_bw_points($xi, $yi, $x2, $y2) > 4*$w; $yi = $yi+2*$w+$step)
			 	{
					$xi = $this->getposx_line($yi, $x1, $y1, $x2, $y2);
					# note: GD back-compatability?
					if ($solid && $gd_ver[1] >= 2)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* not $solid */
					if ($solid && $gd_ver[1] < 2)
						imagearc($im, $xi, $yi, 2*$w+2, 2*$w+2, 0, 360, $color);
				} /* for $yi = $y1+$w */
			} else {
				$xi = $this->getposx_line($y1-$w, $x1, $y1, $x2, $y2);
				for ($yi = $y1-$w; $this->dist_bw_points($xi, $yi, $x2, $y2) > 4*$w; $yi = $yi-2*$w-$step)
			 	{
					$xi = $this->getposx_line($yi, $x1, $y1, $x2, $y2);
					if ($solid && $gd_ver[1] >= 2)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* not $solid */
					if ($solid && $gd_ver[1] < 2)
						imagearc($im, $xi, $yi, 2*$w+2, 2*$w+2, 0, 360, $color);
				} /* for $yi = $y1-$w */
			} /* not $y1 < $y2 */
		} /* not $dif_horizontal */
		$point[0] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[1] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[2] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[3] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[4] = $x2;
		$point[5] = $y2;
		$point[6] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[7] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[8] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[9] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -$w);
		if ($solid == 1)
	 	{
			imagefilledpolygon($im, $point, 5, $color);
		}
		else
	 	{
			imagepolygon($im, $point, 5, $color);
		} /* not $solid */
		return 0;
	}
	# desc: not used and ready for deletion?;
	# @return: image;
	public function draw_arrow_dot($im, $x1, $y1, $x2, $y2, $w, $solid, $color)
 	{
		$point[0] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, $w);
		$point[1] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, $w);
		$point[2] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[3] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[6] = $x2;
		$point[7] = $y2;
		$point[8] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[9] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[10] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[11] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[12] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[13] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		if ($solid)
	 	{
			imagefilledPolygon($im, $point, 7, $color);
			$style = array($this->white, 'IMG_COLOR_TRANSPARENT', 'IMG_COLOR_TRANSPARENT', 'IMG_COLOR_TRANSPARENT');
			imagesetstyle($im, $style);
			imagesetthickness($im, 10);
			imageline($im, $this->middle($point[0], $point[12]), $this->middle($point[1],$point[13]),
			 	$point[6], $point[7], IMG_COLOR_STYLED);
			imagesetthickness($im, 1);
			imagepolygon($im, $point, 7, $this->black);
		}
		else
	 	{
			imagepolygon($im, $point, 7, $this->black);
		} /* not $solid */
		return $im;
	}
	# @return: image;
	public function draw_rectangle($im, $x1, $y1, $x2, $y2, $w, $solid, $color)
 	{
		$point[0] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, $w);
		$point[1] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, $w);
		$point[2] = $x2 + $this->newx($x2-$x1, $y2-$y1, 0, $w);
		$point[3] = $y2 + $this->newy($x2-$x1, $y2-$y1, 0, $w);
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		$point[6] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[7] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		if ($this->black == -1)
			$this->define_colors($im);
		if ($solid)
	 	{
			imagefilledPolygon($im, $point, 4, $color);
			imagepolygon($im, $point, 4, $this->black);
		}
		else
	 	{
			imagepolygon($im, $point, 4, $this->black);
		} /* not $solid */
		return $im;
	}
	# @return: image;
	public function draw_rectangle_half($im, $x1, $y1, $x2, $y2, $w, $solid, $color)
 	{
		$point[0]=$x1;
		$point[1]=$y1;
		$point[2]=$x2;
		$point[3]=$y2;
		$point[4]=$x2 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[5]=$y2 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		$point[6]=$x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[7]=$y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		if ($this->black == -1)
			$this->define_colors($im);
		if ($solid)
	 	{
			imagefilledPolygon($im, $point, 4, $color);
			imagepolygon($im, $point, 4, $this->black);
		}
		else
	 	{
			imagepolygon($im, $point, 4, $this->black);
		} /* not $solid */
		return $im;
	}

	public function draw_circle3($im, $x1, $y1, $x2, $y2, $w, $step, $solid, $color)
 	{
		$dif_horizontal = abs($x1-$x2);
		$dif_vertical = abs($y1-$y2);
		if ($dif_horizontal > $dif_vertical)
	 	{
			if ($x1 < $x2)
		 	{
				$yi = $this->getposy_line(($x1+$w), $x1, $y1, $x2, $y2);
				for ($xi = $x1+$w; $this->dist_bw_points($xi, $yi, $x2, $y2) > 2*$w; $xi = $xi+2*$w+$step)
			 	{
					$yi = $this->getposy_line($xi, $x1, $y1, $x2, $y2);
					if ($solid)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* not $solid */
				} /* for $xi = $x1+$w */
			}
			else 
			{
				$yi = $this->getposy_line(($x1-2*$w), $x1, $y1, $x2, $y2);
				for ($xi = $x1-2*$w; $this->dist_bw_points($xi, $yi, $x2, $y2) > 2*$w; $xi = $xi-2*$w-$step)
			 	{
					$yi = $this->getposy_line($xi, $x1, $y1, $x2, $y2);
					if ($solid)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					}
				} /* for $xi=$x1-2*$w */
			} /* not if $x1 < $x2 */
		}
		else
	 	{
			if ($y1 < $y2)
		 	{
				for ($yi = $y1; $this->dist_bw_points($xi, $yi, $x2, $y2) > 2*$w; $yi = $yi+2*$w+$step)
			 	{
					$xi = $this->getposx_line($yi, $x1, $y1, $x2, $y2);
					if ($solid)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* not $solid */
				} /* for $yi = $y1 */
			}
			else
		 	{
				$xi = $this->getposx_line(($y1-2*$w), $x1, $y1, $x2, $y2);
				for ($yi = $y1-2*$w; $this->dist_bw_points($xi, $yi, $x2, $y2) > 2*$w; $yi = $yi-2*$w-$step)
			 	{
					$xi = $this->getposx_line($yi, $x1, $y1, $x2, $y2);
					if ($solid)
				 	{
						imagefilledarc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color, IMG_ARC_PIE);
					}
					else
				 	{
						imagearc($im, $xi, $yi, 2*$w, 2*$w, 0, 360, $color);
					} /* if $solid */
				} /* for $yi=$y1 */
			} /* not $y1 */
		} /* not $dif_horizontal */
		return 0;
	}
	
	public function draw_rectangle_half_map($x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $w = 0)
 	{
		$point = array();
		$point[0] = $x1;
		$point[1] = $y1;
		$point[2] = $x2;
		$point[3] = $y2;
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		$point[6] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[7] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		foreach ($point as $k=>$v)
			$point[$k] = floor($v);
		$retval = implode(",", $point);
		return $retval;
	}
	
	public function draw_arrow_map($x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $w = 0)
 	{
		$point = array();
		$point[0] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, $w);
		$point[1] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, $w);
		$point[2] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[3] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, $w);
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, 2*$w);
		$point[6] = $x2;
		$point[7] = $y2;
		$point[8] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[9] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -2*$w);
		$point[10] = $x2 + $this->newx($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[11] = $y2 + $this->newy($x2-$x1, $y2-$y1, -4*$w, -$w);
		$point[12] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[13] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		foreach ($point as $k=>$v)
			$point[$k] = floor($v);
		$retval = implode(",", $point);
		return $retval;
	}

	public function draw_arrow_half_map($x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $w = 0)
 	{
		$point = array();
		$point[0] = $x1;
		$point[1] = $y1;
		$point[2] = $x2;
		$point[3] = $y2;
		$point[4] = $x2 + $this->newx($x2-$x1, $y2-$y1, -6*$w, -3*$w);
		$point[5] = $y2 + $this->newy($x2-$x1, $y2-$y1, -6*$w, -3*$w);
		$point[6] = $x2 + $this->newx($x2-$x1, $y2-$y1, -6*$w, -$w);
		$point[7] = $y2 + $this->newy($x2-$x1, $y2-$y1, -6*$w, -$w);
		$point[8] = $x1 + $this->newx($x2-$x1, $y2-$y1, 0, -$w);
		$point[9] = $y1 + $this->newy($x2-$x1, $y2-$y1, 0, -$w);
		foreach ($point as $k=>$v)
			$point[$k] = floor($v);
		$retval = implode(",", $point);
		return $retval;
	}
	# $xpos, $ypos, $font: int;
	# $string: string;
	# @return: string;
	public function draw_label_map($xpos, $ypos, $string, $font)
 	{
		$pix_width = imagefontwidth($font)*strlen($string);
		$pix_height = imagefontheight($font);
		$pad = 2;
		$point = array();
		$point[0] = $xpos-$pix_width/2-$pad-2;
		$point[1] = $ypos-$pix_height/2-$pad+1;
		$point[2] = $xpos+$pix_width/2+$pad+1;
		$point[3] = $ypos+$pix_height/2+$pad;
		foreach ($point as $k=>$v)
			$point[$k] = floor($v);
		$retval = implode(",", $point);
		return $retval;
	}
	# $xpos, $ypos, $font: int;
	# $string: string;
	# @return: string;
	public function draw_label_round_map($xpos, $ypos, $string, $font)
	{
		$radius = 10;
		$point = array();
		$point[0] = $xpos;
		$point[1] = $ypos;
		$point[2] = $radius;
		foreach ($point as $k=>$v)
			$point[$k] = floor($v);
		$retval = implode(",", $point);
		return $retval;
	}
	# $string: string;
	#	$font: int;
	#	$textcolor, $bgcolor: colour;
	#	@return: GD_image;
	public function draw_internode($string, $font, $textcolor, $bgcolor)
 	{
		$radius = 7;
		$pix_width = 2*$radius;
		$pix_height = 2*$radius;
		$im = @imagecreate($pix_width+2, $pix_height+2)
		 	or die ("Cannot Initialize new GD image stream");
		$whiteinter = imagecolorallocate($im, 255, 255, 255);
		imagecolortransparent($im, $whiteinter);
		$black = imagecolorallocate($im, 0,0,0);
		$red = imagecolorallocate($im, 255, 0, 0);
		$blue = imagecolorallocate($im, 0, 0, 255);
		$yellow=imagecolorallocate($im, 255, 255, 0);
		$gd_ver = $this->get_gd_ver();
		# note: GD back-compatability?
		if($gd_ver[1] < 2)
	 	{
			imagearc($im, $radius+1, $radius+1, 2*$radius, 2*$radius, 0, 360, $blue);
		}
		else
	 	{
			imagefilledellipse($im, $radius+1, $radius+1, 2*$radius, 2*$radius, $blue);
			imageellipse($im, $radius+1, $radius+1, 2*$radius, 2*$radius, $black);
		} /* not $gd_ver[1] */
		imagestring($im, 'gdTinyFont', $radius,
		 	$radius-imagefontwidth('gdTinyFont')*strlen($string)/2, $string, $yellow);
		return $im;
	}

	public function labelv2($string, $font, $fgcolor, $bgcolor)
 	{
		$pix_width = imagefontwidth($font)*strlen($string);
		$pix_height = imagefontheight($font);
		$pad = 2;
		$im = @imagecreate($pix_width+$pad*2+4, $pix_height+$pad*2)
		 	or die ("Cannot Initialize new GD image stream");
		# allocate fg color
		if (($fgdec = $this->hex2dec($fgcolor)) == false)
	 	{
			$fgcolor = imagecolorallocate($im, 0, 0, 0);
		}
		else
	 	{
			$fgcolor = imagecolorallocate($im, $fgdec[0], $fgdec[1], $fgdec[2]);
		} /* not $fgdec */
		if (($bgdec = $this->hex2dec($bgcolor)) == false)
	 	{
			$bgcolor = imagecolorallocate($im, 255, 255, 255);
		}
		else
	 	{
			$bgcolor = imagecolorallocate($im, $bgdec[0], $bgdec[1], $bgdec[2]);
		} /* not $bgdec */
		imagefilledrectangle($im, 0, 0, $pix_width+$pad*2+4, $pix_height+$pad*2-1, $fgcolor);
		imagefilledrectangle($im, 1, 1, $pix_width+$pad*2+2, $pix_height+$pad*2-2, $bgcolor);
		imagestring($im, $font, 0+$pad+2, 0+$pad/2, $string, $fgcolor);
		return $im;
	}

	public function label($im, $string, $xpos, $ypos, $font, $textcolor, $bgcolor)
 	{
		$pix_width = imagefontwidth($font)*strlen($string);
		$pix_height = imagefontheight($font);
		$pad = 2;
		imagefilledrectangle($im, $xpos-$pix_width/2-$pad-2, $ypos-$pix_height/2-$pad+1,
		 	$xpos+$pix_width/2+$pad+1, $ypos+$pix_height/2+$pad, $textcolor);
		imagefilledrectangle($im, $xpos-$pix_width/2-$pad-1, $ypos-$pix_height/2-$pad+2,
		 	$xpos+$pix_width/2+$pad, $ypos+$pix_height/2+$pad-1, $bgcolor);
		imagestring($im, $font, $xpos-$pix_width/2, $ypos-$pix_height/2, $string, $textcolor);
		return $im;
	}

	public function label_round($im, $string, $xpos, $ypos, $font, $textcolor, $bgcolor)
	{
		$radius = 10;
		$pix_width = imagefontwidth($font)*strlen($string);
		$pix_height = imagefontheight($font);
		if ($this->black == -1)
			$this->define_colors($im);
		$gd_ver = $this->get_gd_ver();
		if($gd_ver[1] >= 2)
	 	{ 
			imagefilledellipse($im, $xpos, $ypos, 2*$radius, 2*$radius, $bgcolor);
			imageellipse($im, $xpos, $ypos, 2*$radius, 2*$radius, $this->black);
			imagestring($im, $font-1, $xpos-$pix_width/2, $ypos+$radius, $string, $textcolor);
		}
		else
	 	{
			for($tmp = -$pix_height; $tmp <= $radius; $tmp++)
		 	{
				imagearc($im, $xpos, $ypos, $pix_width+$tmp, $pix_height+$tmp, 0, 360, $bgcolor);
			} /* for $tmp */
			imagearc($im, $xpos, $ypos, $pix_width+$radius, $pix_height+$radius, 0, 360, $this->black);
			imagestring($im, $font-1, $xpos-$pix_width/2, $ypos-$radius/2+1, $string, $textcolor);
		} /* not $gd_ver */
		return $im;
	}
	# $im: image stream;
	# $string: string/text;
	# $nodea: stdclass with structure x/y pos;
	# $nodeb: stdclass with structure x/y pos;
	# $font: int;
	# $bgcolor: color;
	# $fgcolor: color;
	# @return: image;
	# desc: this is actually function for function :|
	# 			this whole function is one big fixme, but it looked
	# 			like waste of precious time. i've patched up wounds
	# 			and	left it for another time.
	public function valuesHalf($im, $nodea, $nodeb, $rate = 0, $pctrate = 0, $font = 3,
	 	$arrow_width = 4, $fgcolor, $bgcolor)
 	{
		$var = $this->toDisplay($rate);
		if ($nodea->x != $nodeb->x)
	 	{
			if ($nodea->x < $nodeb->x)
		 	{
				$factorx = -1;
				$factory = 1;
			}
			else
		 	{
				$factorx = 1;
				$factory = -1;
			} /* not if $nodea->x */
			$correction = 0;
			$x = $nodea->x + $this->newx($nodea->x - $nodeb->x, $nodea->y - $nodeb->y,
				(-10)*$arrow_width, (-4)*$arrow_width) - $factorx * (imagefontwidth($font - 1)
			 	* (strlen($var) - strlen("{$pctrate}%"))/2);
			$y = $nodea->y + $this->newy($nodea->x - $nodeb->x, $nodea->y - $nodeb->y,
				(-10)*$arrow_width, (-4)*$arrow_width) + $factory * (imagefontheight($font - 1)
				+ $arrow_width);
		}
		else
	 	{
			if ($nodea->y < $nodeb->y)
		 	{
				$factorx = 1;
				$factory = 1;
			}
			else
		 	{
				$factorx = -1;
				$factory = -1;
			} /* not $nodea->y */
			$correction = $arrow_width * $factorx + $factorx;
			$x = $nodea->x + $this->newx($nodea->x - $nodeb->x, $nodea->y - $nodeb->y,
				(-10)*$arrow_width, (-4)*$arrow_width) - $factorx * (imagefontwidth($font - 1)
			 	* (strlen($var) - strlen("{$pctrate}%"))/2) - $factorx;
			$y = $nodea->y + $this->newy($nodea->x - $nodeb->x, $nodea->y - $nodeb->y,
				(-10)*$arrow_width, (-4)*$arrow_width) + $factory * (imagefontheight($font - 1)
				+ $arrow_width) + $factory * $arrow_width;

		} /* not $nodea->x < $nodeb->x */
		# show % label
		$this->label($im, "{$pctrate}%", $nodea->x + $this->newx($nodea->x - $nodeb->x,
			$nodea->y - $nodeb->y, (-10)*$arrow_width, (-3)*$arrow_width) - $correction,
			$nodea->y + $this->newy($nodea->x - $nodeb->x,$nodea->y - $nodeb->y, 
			(-10)*$arrow_width, (-3)*$arrow_width) + $factory, $font - 1, $fgcolor, 
			$bgcolor);
		# show rate label
		$this->label($im, $var, $x, $y,	$font - 1, $fgcolor, $bgcolor);
		return $im;		
	}
	# @return: color;
	public function select_color($im, $rate, $scale)
 	{
		# allocate default color
		$retcolor = NULL;
		if ($rate == "0")
	 	{
			$retcolor = imagecolorClosest($im, 128, 128, 128);
		}
		else
	 	{
			foreach ($scale->entry as $entry)
		 	{
				if (($entry->low <= $rate) && ($rate <= $entry->high))
			 	{
					$retcolor = imagecolorallocate($im, $entry->r, $entry->g, $entry->b);
					if ($retcolor == -1 || $retcolor == false)
						$retcolor = imagecolorClosest($im, $entry->r, $entry->g, $entry->b);
					break;
				} /* not $scale->low */
			} /* foreach $scale->entry */
		} /* not $rate == 0 */
		return $retcolor;
	}
	# @return: int;
	public function define_colors($im)
 	{
		$this->white = imagecolorallocate($im, 255, 255, 255);
		if ($this->white == "-1")
			$this->white = imagecolorclosest($im, 255, 255, 255);
		$this->red = imagecolorallocate($im, 255, 0, 0);
		if ($this->red == "-1")
			$this->red = imagecolorClosest($im, 255, 0, 0);
		$this->darkgray = imagecolorallocate($im, 128, 128, 128);
		if ($this->darkgray == "-1")
			$this->darkgray = imagecolorClosest($im, 128, 128, 128);
		$this->gray = imagecolorallocate($im, 248, 248, 248);
		if ($this->gray == "-1")
			$this->gray = imagecolorClosest($im, 248, 248, 248);
		$this->orange = imagecolorallocate($im, 220, 210, 60);
		if ($this->orange == "-1")
			$this->orange = imagecolorClosest($im, 220, 210, 60);
		$this->black = imagecolorallocate($im, 0, 0, 0);
		if ($this->black == "-1")
			$this->black = imagecolorClosest($im, 0, 0, 0);
		$this->green = imagecolorallocate($im, 0, 255, 0);
		if ($this->green == -1)
			$this->green= imagecolorClosest($im, 0, 255, 0);
		return 0;
	}
	
	public function draw_title($title, $font, $titleforeground_red, $titleforeground_green,
		$titleforeground_blue, $titlebackground_red, $titlebackground_green,
		$titlebackground_blue, $unixtime)
 	{
		$t = date("D M d H:i:s Y", $unixtime);
		if (imagefontwidth(2)*strlen("Last update on $t") > imagefontwidth($font)*strlen($title))
	 	{
			$titlewidth = imagefontwidth($font-2)*strlen("Last update on $t");
		}
		else
	 	{
			$titlewidth = imagefontwidth($font)*strlen($title);
		} /* not imagefontwidth */
		$im = @imagecreate ($titlewidth+5, imagefontheight($font)*2+5)
		 	or die ("Cannot Initialize new GD image stream");
		# title background
		$titlebackground = imagecolorAllocate($im, $titlebackground_red, $titlebackground_green,
		 	$titlebackground_blue);
		if ($titlebackground == "-1")
		{
			$titlebackground = imagecolorClosest($im, $titlebackground_red, $titlebackground_green,
				$titlebackground_blue);
		} /* not $titlebackground */
		# title foreground
		$titleforeground = imagecolorAllocate($im, $titleforeground_red, $titleforeground_green,
		 	$titleforeground_blue);
		if ($titleforeground == "-1")
	 	{
			$titleforeground = imagecolorClosest($im, $titleforeground_red, $titleforeground_green,
			 	$titleforeground_blue);
		} /* not $titleforeground */
		imagefilledrectangle($im, 0, 0, $titlewidth+3, imagefontheight($font)*2+3, $titlebackground);
		imagerectangle($im, 0, 0, $titlewidth+4, imagefontheight($font)*2+4, $titleforeground);
		imagestring($im, $font, 2, 2, $title, $titleforeground);
		imagestring($im, $font-2, 2, imagefontheight($font)+4, "Last update on $t", $titleforeground);
		return $im;
	}
	# $scale: object format in $scale->entry->key = value
	public function draw_legend($label = "default", $font = 3, $scale)
 	{
		$strwidth = imagefontwidth($font);
		$strheight = imagefontheight($font);
		$scalecount = count($scale->entry);
		# Create legend image
		$im = @imagecreate($strwidth * strlen($label) + 11, $strheight * ($scalecount + 1) 
			+ 11 + imagefontheight(1) * 2) or die ("Cannot Initialize new GD image stream");
		# Define colors
		$white = imagecolorallocate($im, 255, 255, 255);
		$orange = imagecolorallocate($im, 220, 210, 60);
		$black = imagecolorallocate($im, 0,0,0);
		$gray = imagecolorallocate($im, 248, 248, 248);
		$textcolor = imagecolorallocate($im, 0, 0, 0);
		# Scalecolor array
		$scalecolor = array();
		foreach ($scale->entry as $entry)
	 	{
			$scalecolor[$entry->low . ":" . $entry->high] = imagecolorallocate($im, $entry->r, $entry->g, $entry->b);
			if ($scalecolor[$entry->low . ":" . $entry->high] == "-1")
				$scalecolor[$entry->low . ":" . $entry->high] = imagecolorClosest($im, $entry->r, $entry->g, $entry->b);
		} /* foreach $scale->entry */
		imagefilledrectangle($im, 0, 0, $strwidth * strlen($label) + 10, $strheight * ($scalecount + 1)
		 	+ 10 + imagefontheight(1) * 2, $black);
		imagefilledrectangle($im, 0, 0, $strwidth * strlen($label) + 10, $strheight * ($scalecount + 1)
		 	+ 10 + imagefontheight(1), $gray);
		imagerectangle($im, 0, 0, $strwidth * strlen($label) + 10, $strheight * ($scalecount + 1) + 10
		 	+ imagefontheight(1) * 2, $black);
		imagestring($im, $font, 4, 4, $label, $black);
		$i = 0;
		foreach ($scale->entry as $entry)
	 	{
			imagefilledrectangle($im, 6, $strheight * ($i + 1) + 8, 6 + 16, $strheight * ($i + 1)
			 	+ $strheight + 6,	$scalecolor["{$entry->low}:{$entry->high}"]);
			imagestring($im, $font, 6 + 20, $strheight * ($i + 1) + 8,
			 	$entry->low . "-" . $entry->high . "%", $black);
			$i++;
		} /* foreach $scale->entry */
		imagestring($im, 1, (($strwidth * strlen($label) + 10) - imagefontwidth(1)
		 	* strlen("WeatherMap5RRD")) / 2, $strheight*($i+1)+18, "WeatherMap5RRD", $white);
		# unset scalecolor array and free(?) memory
		unset($scalecolor);
		return $im;
	}
	# $scale: object format in $scale->entry->key = value
	public function draw_legend2($label, $font, $scale)
 	{
		$strwidth = imagefontwidth($font);
		$strheight = imagefontheight($font);
		$scalecount = count($scale->entry);
		$x = $scalecount * 36 + 6 + 1 + $strwidth * 4;
		$y = 6 + $strheight * 2 + 23;
		$im = @imagecreate($x, $y) or die ("Cannot Initialize new GD image stream");
		$white = imagecolorallocate($im, 255, 255, 255);
		$orange = imagecolorallocate($im, 220, 210, 60);
		$black = imagecolorallocate($im, 0, 0, 0);
		$gray = imagecolorallocate($im, 248, 248, 248);
		$textcolor = imagecolorallocate($im, 0, 0, 0);
		foreach ($scale->entry as $entry)
	 	{
			$scalecolor[$entry->low . ":" . $entry->high] = imagecolorallocate($im, $entry->r, $entry->g, $entry->b);
			if ($scalecolor[$entry->low . ":" . $entry->high] == "-1")
				$scalecolor[$entry->low . ":" . $entry->high] = imagecolorClosest($im, $entry->r, $entry->g, $entry->b);
		} /* foreach $scale->entry */
		imagestring($im, $font, 4, 4, $label, $black);
		$i = 0;
		foreach ($scale->entry as $entry)
	 	{
			imagefilledrectangle($im, 6 + 36 * $i, 23, 6 + ($i + 1) * 36, 23 + 10,
			 	$scalecolor["{$entry->low}:{$entry->high}"]);
			imagerectangle($im, 6 + 36 * $i, 23, 6 + ($i + 1) * 36, 23 + 10, $black);
			imagestring($im, $font, 6 + ($i + 1) * 36 - 5, 23 + 12, $entry->high, $black);
			$i++;
		} /* foreach $scale->entry */
		# show '%' after the last $scale->entry[$i-1] value
		# note: entries are indexed 0-x, but $i is +1 because of foreach
		imagestring($im, $font, 6 + ($i) * 36 + strlen($scale->entry[$i-1]->high) * $strwidth,
		 	23 + 12, "%", $black);
		imagestring($im, 1, 6 + ($i) * 36 - strlen("WeatherMap5RRD") * imagefontwidth(1), 23 - 10,
		 	"WeatherMap5RRD", $black);
		return $im;
	}
	# $im - png image
	# $nodefrom - array with x, y keys and int values
	# $nodeto - array with x, y keys and int values
	# $input - int
	# $output - int
	# $domiddle - int; note: 1 for PtP link, 0 for arrows pointing straight to inode
	public function displayValue($im, $nodefrom, $nodeto, $rate = 0, $domiddle = 1)
 	{
		if ($rate >=125999)
	 	{
			$coefdisplay=8/(1000*1000);
			$unitdisplay="Mbits";
		} 
		else
	 	{
			$coefdisplay=8/1000;
			$unitdisplay="Kbits";
		} /* not $rate */
		$var = $rate * $coefdisplay;
		$todisplay = round($var, 1) . " {$unitdisplay}";
		if ($this->black == -1 || $this->white == -1)
			$this->define_colors($im);
		if ($domiddle == 1)
	 	{
			$this->label($im, "{$todisplay}", $this->middle($nodeto->x, $this->middle($nodefrom->x, $nodeto->x)),
				$this->middle($nodeto->y, $this->middle($nodefrom->y, $nodeto->y+70)), $this->font, $this->black, $this->white);
		}
		else
	 	{
			/* why fifty? well, i don't know. it seems like *double* middle *negates* +senventy up there more, than one middle
			 * i hope +fifty will be okay
			 * calculates half-way of PtP, not one-fourth like for arrow-to-arrow
			*/
			$this->label($im, "{$todisplay}", $this->middle($nodeto->x, $nodefrom->x),
				$this->middle($nodefrom->y, $nodeto->y+50), $this->font, $this->black, $this->white);
		} /* not $domiddle */
	}
	# $rate: int;
	# @return: string;
	public function toDisplay($rate = 0)
 	{
		if ($rate >=125999)
	 	{
			# coefdisplay
			$rate = $rate * (8/(1000*1000));
			$unitdisplay="Mbits";
		}
		else
	 	{
			# coefdisplay
			$rate = $rate * (8/1000);
			$unitdisplay="Kbits";
		} /* not $rate */
		$retval = round($rate, 1) . " {$unitdisplay}";
		return $retval;
	}
	# desc: converts color in hex to dec(?);
	# $color: color;
	# @return: int;
	public function hex2dec($color)
 	{
		$hexcolor = array();
		$deccolor = array();
		$hexcolor = str_split($color, 2);
		foreach ($hexcolor as $foo)
	 	{
			array_push($deccolor, hexdec($foo));
		} /* foreach $hexcolor */
		if (count($deccolor) == 3)
	 	{
			return $deccolor;
		} else {
			return false;
		} /* not count($deccolor) */
	}
}
?>
Return current item: Weathermap5rrd