Current Path : /var/www/html/soar-backup/wp-content/plugins/formcraft3/lib/eos/ |
Current File : /var/www/html/soar-backup/wp-content/plugins/formcraft3/lib/eos/Graph.php |
<?php namespace jlawrence\eos; // fun class that requires the GD libraries to give visual output to the user /** * Equation Graph * * Fun class that requires the GD libraries to give visual output of an * equation to the user. Extends the Parser class. * * @author Jon Lawrence <jlawrence11@gmail.com> * @copyright Copyright ©2005-2013 Jon Lawrence * @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License * @package Math * @subpackage EOS * @version 3.x */ class Graph { private static $width = 640; private static $height = 480; /** * @var resource */ private static $image; public static $labelAxis = true; public static $backgroundColor = array(255, 255, 255); public static $gridColor = array(150, 150, 150); public static $axisColor = array(0, 0, 0); public static $lineColor = array(0, 0, 0); /** * Initializer * * Sets up the Graph class with an image width and height defaults to * 640x480 * * @param int $width Image width * @param int $height Image height */ public static function init($width = 640, $height = 480) { // default width and height equal to that of a poor monitor (in early 2000s) self::$width = $width; self::$height = $height; // initialize main class Parser::init(); //can't really mess this up, return true return true; } /** * Create GD Graph Image * * Creates a GD image based on the equation given with the parameters that are set * * @param string $eq Equation to use. Needs variable in equation to create graph, all variables are interpreted as 'x' * @param integer $xLow Lower x-bound for graph * @param integer $xHigh Upper x-bound for graph * @param float $xStep Stepping points while solving, the lower, the better precision. Slow if lower than .01 * @param bool $xyGrid Draw grid-lines? * @param bool $yGuess Guess the upper/lower yBounds? * @param int $yLow Lower y-bound * @param int $yHigh Upper y-bound * @return null */ public static function graph($eq, $xLow, $xHigh, $xStep = null, $xyGrid = false, $yGuess = true, $yLow = null, $yHigh = null) { //create our image and allocate the two colors $img = ImageCreate(self::$width, self::$height); //The following noinspection needed because the first color allocated is the background, but not used for anything else. /** @noinspection PhpUnusedLocalVariableInspection */ $bgColor = ImageColorAllocate($img, self::$backgroundColor[0], self::$backgroundColor[1], self::$backgroundColor[2]); $aColor = ImageColorAllocate($img, self::$axisColor[0], self::$axisColor[1], self::$axisColor[2]); $lColor = ImageColorAllocate($img, self::$lineColor[0], self::$lineColor[1], self::$lineColor[2]); $gColor = ImageColorAllocate($img, self::$gridColor[0], self::$gridColor[1], self::$gridColor[2]); //$black = ImageColorAllocate($img, 0, 0, 0); //$grey = ImageColorAllocate($img, 150, 150, 150); //$darkGrey = ImageColorAllocate($img, 50, 50, 50); if ($xLow > $xHigh) list($xLow, $xHigh) = array($xHigh, $xLow); //swap function //Smart xStep calc if ($xStep == false) { $xStep = ($xHigh - $xLow) / self::$width; } $xStep = abs($xStep); $hand = null; $xVars = array(); //If yGuess is true, make sure yLow and yHigh are not set if ($yGuess) { $yLow = null; $yHigh = null; } //We want to limit the number of lines/ticks/etc so graph remains readable, set max now $xMaxLines = 30; $yMaxLines = 30; //DEVELOPER, UNCOMMENT NEXT LINE IF WANTING TO PREVENT SLOW GRAPHS //$xStep = ($xStep < .01) ? $xStep : 0.01; $xScale = self::$width / ($xHigh - $xLow); $counter = 0; // @codeCoverageIgnoreStart if (Math::$DEBUG) { $hand = fopen("Graph.txt", "w"); fwrite($hand, "$eq\n"); } // @codeCoverageIgnoreEnd for ($i = $xLow; $i <= $xHigh; $i += $xStep) { $tester = sprintf("%10.3f", $i); if ($tester == "-0.000") $i = 0; $y = Parser::solve($eq, $i); //eval('$y='. str_replace('&x', $i, $eq).";"); /* used to debug my Parser class results */ // @codeCoverageIgnoreStart if (Math::$DEBUG) { $tmp1 = sprintf("y(%5.3f) = %10.3f\n", $i, $y); fwrite($hand, $tmp1); } // @codeCoverageIgnoreEnd // If developer asked us to find the upper and lower bounds for y... if ($yGuess == true) { $yLow = ($yLow === null || ($y < $yLow)) ? $y : $yLow; $yHigh = ($yHigh === null || $y > $yHigh) ? $y : $yHigh; } $xVars[$counter] = $y; $counter++; } //Now that we have all the variables stored...find the yScale $yScale = self::$height / (($yHigh) - ($yLow)); // @codeCoverageIgnoreStart //Calculate the stepping points for lines now if ($yHigh - $yLow > $yMaxLines) { $yJump = ceil(($yHigh - $yLow) / $yMaxLines); } else { $yJump = 1; } if ($xHigh - $xLow > $xMaxLines) { $xJump = ceil(($xHigh - $xLow) / $xMaxLines); } else { $xJump = 1; } // @codeCoverageIgnoreEnd // add 0.01 to each side so that if y is from 1 to 5, the lines at 1 and 5 are seen $yLow -= 0.01; $yHigh += 0.01; // @codeCoverageIgnoreStart if (Math::$DEBUG) { fwrite($hand, $yLow . " -- " . $yHigh . "\n"); } // @codeCoverageIgnoreEnd // if developer wanted a grid on the graph, add it now if ($xyGrid == true) { // @codeCoverageIgnoreStart if (Math::$DEBUG) { fwrite($hand, "Drawing Grid\n"); } // @codeCoverageIgnoreEnd for ($i = ceil($yLow); $i <= floor($yHigh); $i += $yJump) { $i0 = abs($yHigh - $i); ImageLine($img, 0, $i0 * $yScale, self::$width, $i0 * $yScale, $gColor); imagestring($img, 1, 2, $i0 * $yScale + 2, $i, $gColor); } for ($i = ceil($xLow); $i <= floor($xHigh); $i += $xJump) { $i0 = abs($xLow - $i); ImageLine($img, $i0 * $xScale, 0, $i0 * $xScale, self::$height, $gColor); imagestring($img, 1, $i0 * $xScale + 2, 2, $i, $gColor); } } //Now that we have the scales, let's see if we can draw an x/y-axis if ($xLow <= 0 && $xHigh >= 0) { //the y-axis is within our range - draw it. $x0 = abs($xLow) * $xScale; ImageLine($img, $x0, 0, $x0, self::$height, $aColor); for ($i = ceil($yLow); $i <= floor($yHigh); $i += $yJump) { $i0 = abs($yHigh - $i); ImageLine($img, $x0 - 3, $i0 * $yScale, $x0 + 3, $i0 * $yScale, $aColor); //If we want the axis labeled... (call in the allies?) if (self::$labelAxis) { imagestring($img, 1, $x0 + 2, $i0 * $yScale + 1, $i, $aColor); } } } if ($yLow <= 0 && $yHigh >= 0) { //the x-axis is within our range - draw it. $y0 = abs($yHigh) * $yScale; ImageLine($img, 0, $y0, self::$width, $y0, $aColor); //Create ticks for y for ($i = ceil($xLow); $i <= floor($xHigh); $i += $xJump) { $i0 = abs($xLow - $i); ImageLine($img, $i0 * $xScale, $y0 - 3, $i0 * $xScale, $y0 + 3, $aColor); //If we want the axis labeled.... if (self::$labelAxis) { imagestring($img, 1, $i0 * $xScale + 2, $y0 + 1, $i, $aColor); } } } $counter = 1; //now graph it all ;] for ($i = $xLow + $xStep; $i <= $xHigh; $i += $xStep) { $x1 = (abs($xLow - ($i - $xStep))) * $xScale; $y1 = (($xVars[$counter - 1] < $yLow) || ($xVars[$counter - 1] > $yHigh)) ? -1 : (abs($yHigh - $xVars[$counter - 1])) * $yScale; $x2 = (abs($xLow - $i)) * $xScale; $y2 = (($xVars[$counter] < $yLow) || ($xVars[$counter] > $yHigh)) ? -1 : (abs($yHigh - $xVars[$counter])) * $yScale; // if any of the y values were found to be off of the y-bounds, don't graph those connecting lines if ($y1 != -1 && $y2 != -1) ImageLine($img, $x1, $y1, $x2, $y2, $lColor); $counter++; } // @codeCoverageIgnoreStart if (Math::$DEBUG) { fclose($hand); } // @codeCoverageIgnoreEnd self::$image = $img; } /** * Sends JPG to browser * * Sends a JPG image with proper header to output * * @codeCoverageIgnore */ public static function outJPG() { header("Content-type: image/jpeg"); ImageJpeg(self::$image); } /** * Sends PNG to browser * * Sends a PNG image with proper header to output * * @codeCoverageIgnore */ public static function outPNG() { header("Content-type: image/png"); ImagePng(self::$image); } /** * Output GD Image * * Will give the developer the GD resource for the graph that * can be used to store the graph to the FS or other media * * @return Resource GD Image Resource */ public static function getImage() { return self::$image; } /** * Output GD Image * * Alias for eqGraph::getImage() * * @return Resource GD Image resource */ public static function outGD() { return self::getImage(); } }