com.lokorin.lokorin.lib
[ class tree: com.lokorin.lokorin.lib ] [ index: com.lokorin.lokorin.lib ] [ all elements ]

Source for file lib_graphs.php

Documentation is available at lib_graphs.php

  1. <?php
  2. /*
  3. * Lokorin.com
  4. * Copyright 2004-2006
  5. * Licensed under the GNU LGPL. See COPYING for full terms.
  6. */
  7. /**
  8. * A library for creating and displaying graphs. Graphs takes arrays of values
  9. * and composes images representing the values.
  10. * @author Andreas Launila
  11. * @version $Revision: 1.8 $
  12. * @package com.lokorin.lokorin.lib
  13. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  14. */
  15.  
  16. global $COLOR_BLACK, $COLOR_WHITE;
  17. /**
  18. * RGB array for the color black.
  19. * @var array
  20. * @access private
  21. */
  22. $COLOR_BLACK = array(0, 0, 0);
  23. /**
  24. * RGB array for the color white.
  25. * @var array
  26. * @access private
  27. */
  28. $COLOR_WHITE = array(255, 255, 255);
  29. /**
  30. * The length of the point of the arrow representing the axis.
  31. * @var integer
  32. * @access private
  33. */
  34. define('AXIS_POINT_LENGTH', 10);
  35. /**
  36. * The width of the arrow that represents the axis.
  37. * @var integer
  38. * @access private
  39. */
  40. define('AXIS_WIDTH', 4);
  41. /**
  42. * The number of pixels of length that the label marker of the axis should
  43. * take up.
  44. * @var integer
  45. * @access private
  46. */
  47. define('AXIS_MARKER_SIZE', 5);
  48. /**
  49. * The number of pixels of padding that should be between the axes and the
  50. * graph border.
  51. * @var integer
  52. * @access private
  53. */
  54. define('GRAPH_PADDING', 40);
  55.  
  56. /**
  57. * Draws an arrow with specified paramaters on a specified image.
  58. * @param image $img The image on which the arrow should be drawn.
  59. * @param integer $x1 The x coordinate (pixels) for the starting point of the
  60. * arrow in the image.
  61. * @param integer $y1 The y coordinate (pixels) for the starting point of the
  62. * arrow in the image.
  63. * @param integer $x2 The x coordinate (pixels) for the end point of the arrow
  64. * in the image.
  65. * @param integer $y1 The y coordinate (pixels) for the end point of the arrow
  66. * in the image.
  67. * @param integer $length The length (in pixels) that the actual arrow point
  68. * should have.
  69. * @param integer $width The width (in pixels) that the arrow should have.
  70. * @param array $color The color that the arrow should have, an array with the
  71. * RGB values representing the color.
  72. * @access private
  73. */
  74. function drawArrow(&$img, $x1, $y1, $x2, $y2, $length, $width, $color) {
  75. $distance = sqrt(pow($x1 - $x2, 2) + pow($y1 - $y2, 2));
  76.  
  77. $dx = $x2 + ($x1 - $x2) * $length / $distance;
  78. $dy = $y2 + ($y1 - $y2) * $length / $distance;
  79.  
  80. $k = $width / $length;
  81.  
  82. $x2o = $x2 - $dx;
  83. $y2o = $dy - $y2;
  84.  
  85. $x3 = $y2o * $k + $dx;
  86. $y3 = $x2o * $k + $dy;
  87.  
  88. $x4 = $dx - $y2o * $k;
  89. $y4 = $dy - $x2o * $k;
  90.  
  91. imageline($img, $x1, $y1, $dx, $dy, $color);
  92. imageline($img, $x3, $y3, $x4, $y4, $color);
  93. imageline($img, $x3, $y3, $x2, $y2, $color);
  94. imageline($img, $x2, $y2, $x4, $y4, $color);
  95. }
  96.  
  97. /**
  98. * Draws a specified string with a specified color centered on specified
  99. * coordinates on a specified image.
  100. * @param image $img The image that the string should be drawn on.
  101. * @param integer $font The font that the drawn string should have.
  102. * @param integer $x The x coordinate (pixels) that the drawn string should
  103. * be centered around in the image.
  104. * @param integer $y The y coordinate (pixels) that the drawn string should
  105. * be centered around in the image.
  106. * @param string $string The actual string that should be drawn.
  107. * @param array $color The color that the drawn string should have as an array
  108. * with the RGB values.
  109. * @access private
  110. */
  111. function drawStringCentered(&$img, $font, $x, $y, $string, $color) {
  112. $textWidth = imagefontwidth($font) * strlen($string);
  113. $xLoc = $x + $font - $textWidth / 2;
  114. imagestring($img, $font, $xLoc, $y, $string, $color);
  115. }
  116.  
  117. /**
  118. * Draws a specified string with a specified color aligned right on specified
  119. * coordinates on a specified image.
  120. * @param image $img The image that the string should be drawn on.
  121. * @param integer $font The font that the drawn string should have.
  122. * @param integer $x The x coordinate (pixels) for the rightmost part of
  123. * string.
  124. * @param integer $y The y coordinate (pixels) that the drawn string should
  125. * be centered around in the image.
  126. * @param string $string The actual string that should be drawn.
  127. * @param array $color The color that the drawn string should have as an array
  128. * with the RGB values.
  129. * @access private
  130. */
  131. function drawStringRightAligned(&$img, $font, $x, $y, $string, $color) {
  132. $textWidth = imagefontwidth($font) * strlen($string);
  133. $xLoc = $x - $textWidth;
  134. imagestring($img, $font, $xLoc, $y, $string, $color);
  135. }
  136.  
  137. /**
  138. * Describes a graph that takes values and then transforms them into a
  139. * graphical representation as a graph.
  140. * @author Andreas Launila
  141. * @package com.lokorin.lokorin.lib
  142. */
  143. class Graph {
  144. /**
  145. * Holds all the colors that have been loaded into the graph. The name
  146. * that identifies the color as key, the actual color (RGB array) as value.
  147. * @var array
  148. */
  149. private $colors;
  150. /**
  151. * The number of units that each pixel should represent. The array has two
  152. * keys, 'x' and 'y'.
  153. * @var array
  154. */
  155. private $scale;
  156. /**
  157. * Contains arrays for each function which contain a key 'func' which
  158. * contains a GraphFunction instance, and a key 'color' which contains
  159. * the color identifier to use when drawin the function.
  160. * displayed in the graph.
  161. * @var array
  162. */
  163. private $functions;
  164. /**
  165. * The size, in pixels, of the graph. The array has two keys, 'x' and 'y'.
  166. * @var array
  167. */
  168. private $size;
  169.  
  170. /**
  171. * Constructor for Graph.
  172. * @param integer $width The width, in pixels, that the graph should have.
  173. * @param integer $height The height, in pixels, that the graph should
  174. * have.
  175. */
  176. public function __construct($width = 600, $height = 300) {
  177. $this->size = array(
  178. 'x' => $width,
  179. 'y' => $height
  180. );
  181. //Initialise fields.
  182. global $COLOR_BLACK, $COLOR_WHITE;
  183. $this->colors = array(
  184. 'black' => $COLOR_BLACK,
  185. 'white' => $COLOR_WHITE
  186. );
  187. $this->scale = array(
  188. 'x' => 10,
  189. 'y' => 10
  190. );
  191. $this->functions = array();
  192. }
  193. /**
  194. * Adds a specified color into the graph. Colors have to be loaded before
  195. * they can be used.
  196. * @param string $name The name that should be connected to the color, any
  197. * subsequent uses of this color will have to specify this name.
  198. * @param integer $red A byte [0-255] representing the amount of red in the
  199. * color where 0 is none.
  200. * @param integer $green A byte [0-255] representing the amount of green in
  201. * the color where 0 is none.
  202. * @param integer $blue A byte [0-255] representing the amount of blue in
  203. * the color where 0 is none.
  204. */
  205. public function addColor($name, $red, $green, $blue) {
  206. $this->colors[$name] = array($red, $green, $blue);
  207. }
  208. /**
  209. * Adds a function that should be displayed in the graph.
  210. * @param string $name The name of the function.
  211. * @param array $function A strict function where the key is the function's
  212. * parameter and the corresponding value is the function's value for
  213. * the parameter. Both the parameters and key have to be numerical.
  214. * @param string $color The identifier for the color that should be used
  215. * when drawing the function.
  216. */
  217. public function addFunction($name, $function, $color = 'black') {
  218. $this->functions[] = array(
  219. 'func' => new GraphFunction($name, $function),
  220. 'color' => $color
  221. );
  222. }
  223. /**
  224. * Removes all functions with a specified name.
  225. * @param string $name The name of the function(s) that should be removed,
  226. */
  227. public function removeFunction($name) {
  228. foreach($this->functions as $key => $func) {
  229. if($func->getName() == $name) {
  230. //Remove the function.
  231. unset($this->functions[$key]);
  232. //Continue searching, in case there are more functions with the
  233. //same name
  234. }
  235. }
  236. }
  237. /**
  238. * Constructs and retrieves an image resource representing the graph.
  239. * @param string $backgroundColor The identifier for the color that should
  240. * be used for the background. The default is white.
  241. * @param string $axisColor The identifier for the color that should be
  242. * used for the axes. The default is white.
  243. * @param array $paramMarkers The parameter values that should be marked
  244. * and labeled on the axes.
  245. * @param array $valueMarkers The function values that should be marked
  246. * and labeled on the axes.
  247. * @param string $axisColor The identifier for the color that should be
  248. * used for the axis. The default is black.
  249. * @param callback $paramNameCallback An optional callback which is used
  250. * when labeling the parameters.
  251. * @param callback $valueNameCallback An optional callback which is used
  252. * when labeling the values.
  253. * @param array $viewport Specifies the viewport for graph. I.e. the
  254. * minimum and maximum values and paramters that should be allowed in
  255. * the graph. There are are four keys: 'valMin', 'valMax', 'paramMin',
  256. * 'paramMax'. I.e. min value, max value, min param and max param.
  257. * @param string $gridColor The identifier for the color that should
  258. * be used for the grids. The default is black.
  259. * @param boolean $xGrid True if the x axel should show a grid, false
  260. * otherwise.
  261. * @param boolean $yGrid True if the y axel should show a grid, false
  262. * otherwise.
  263. * @return image An image resource with the graph on it.
  264. */
  265. public function getGraph($backgroundColor = 'white', $axisColor = 'black',
  266. $paramMarkers = array(), $valueMarkers = array(),
  267. $paramNameCallback = '', $valueNameCallback = '',
  268. $viewport = array(), $gridColor = 'black', $xGrid = false,
  269. $yGrid = false) {
  270. //Create the image
  271. $img = imagecreate($this->size['x'], $this->size['y']);
  272. //Load all colors
  273. $colors = array();
  274. foreach($this->colors as $name => $color) {
  275. list($r, $g, $b) = $color;
  276. $colors[$name] = imagecolorallocate($img, $r, $g, $b);
  277. }
  278. //Set the viewport
  279. if(!isset($viewport['valMin'])) {
  280. $viewport['valMin'] = $this->getLowestValue();
  281. }
  282. if(!isset($viewport['valMax'])) {
  283. $viewport['valMax'] = $this->getHighestValue();
  284. }
  285. if(!isset($viewport['paramMin'])) {
  286. $viewport['paramMin'] = $this->getLowestParameter();
  287. }
  288. if(!isset($viewport['paramMax'])) {
  289. $viewport['paramMax'] = $this->getHighestParameter();
  290. }
  291.  
  292. //Calculate the scale (units per pixel), add the axel padding
  293. $paddingX = $paddingY = GRAPH_PADDING;
  294. $dimX = $this->size['x'] - $paddingX;
  295. $dimY = $this->size['y'] - $paddingY;
  296. $scaleX = ($viewport['paramMax'] - $viewport['paramMin']) / $dimX;
  297. $scaleY = ($viewport['valMax'] - $viewport['valMin']) / $dimY;
  298.  
  299. //Create the axes.
  300. if(!isset($colors[$axisColor])) {
  301. $axisColor = 'black';
  302. }
  303. //Convert the param markers to labels.
  304. $paramMin = $this->getLowestParameter();
  305. $paramLabels = array();
  306. foreach($paramMarkers as $marker) {
  307. if($paramNameCallback != '') {
  308. $label = $paramNameCallback($marker);
  309. } else {
  310. $label = $marker;
  311. }
  312. $paramLabels[($marker - $paramMin) / $scaleX] = $label;
  313. }
  314. //Construct the x axis.
  315. $xAxis = new Axis($paramLabels);
  316. $xAxis->setGrid($xGrid);
  317. //Convert the value markers to labels.
  318. $valueMin = min($valueMarkers);
  319. $valueLabels = array();
  320. foreach($valueMarkers as $marker) {
  321. if($valueNameCallback != '') {
  322. $label = $valueNameCallback($marker);
  323. } else {
  324. $label = $marker;
  325. }
  326. $valueLabels[($marker - $valueMin) / $scaleY] = $label;
  327. }
  328. //Construct the y axis.
  329. $yAxis = new Axis($valueLabels);
  330. $yAxis->setGrid($yGrid);
  331. //Set the background
  332. if(!isset($colors[$backgroundColor])) {
  333. $backgroundColor = 'white';
  334. }
  335. imagefilledrectangle($img, 0, 0, $this->size['x'], $this->size['y'],
  336. $colors[$backgroundColor]);
  337.  
  338. //Draw everything
  339. $origo = $this->size['y'] - $paddingY;
  340. $xAxis->drawAxis($img, $colors[$axisColor], $colors[$gridColor],
  341. $paddingX, $origo, $this->size['x'], $origo);
  342. $yAxis->drawAxis($img, $colors[$axisColor], $colors[$gridColor],
  343. $paddingX, $origo, $paddingX, 0);
  344. foreach($this->functions as $function) {
  345. $function['func']->drawFunction($img, $colors[$function['color']], $paddingX,
  346. $paddingY, $this->getHighestParameter(),
  347. min($valueMarkers), max($valueMarkers),
  348. $scaleX, $scaleY);
  349. }
  350. imageinterlace($img, 1);
  351. return($img);
  352. }
  353. /**
  354. * Gets the lowest value defined in the graph.
  355. * @return numeric A value defined in the graph.
  356. */
  357. private function getLowestValue() {
  358. $minValues = array();
  359. foreach($this->functions as $function) {
  360. $minValues[] = $function['func']->getLowestValue();
  361. }
  362. return min($minValues);
  363. }
  364. /**
  365. * Gets the highest value defined in the graph.
  366. * @return numeric A value defined in the graph.
  367. */
  368. private function getHighestValue() {
  369. $maxValues = array();
  370. foreach($this->functions as $function) {
  371. $maxValues[] = $function['func']->getHighestValue();
  372. }
  373. return max($maxValues);
  374. }
  375. /**
  376. * Gets the lowest parameter which has a connected value in the graph.
  377. * @return numeric A parameter from one of the functions.
  378. */
  379. private function getLowestParameter() {
  380. $minParams = array();
  381. foreach($this->functions as $function) {
  382. $minParams[] = $function['func']->getLowestParameter();
  383. }
  384. return min($minParams);
  385. }
  386. /**
  387. * Gets the highest parameter which has a connected value in the graph.
  388. * @return numeric A parameter from one of the functions.
  389. */
  390. private function getHighestParameter() {
  391. $maxParams = array();
  392. foreach($this->functions as $function) {
  393. $maxParams[] = $function['func']->getHighestParameter();
  394. }
  395. return max($maxParams);
  396. }
  397. }
  398.  
  399. /**
  400. * Desribes an graph axis. The axis is graded and can extend those marks to a
  401. * grid if desired. The grades' labels can be altered with callbacks.
  402. * @author Andreas Launila
  403. * @package com.lokorin.lokorin.lib
  404. */
  405. class Axis {
  406. /**
  407. * True if the axis should display a grid, false otherwise. The default is
  408. * false.
  409. * @var boolean
  410. */
  411. private $displayGrid;
  412. /**
  413. * The labels that should be printed along the axis. The key is the
  414. * distance in pixels along the axis that the corresponding value should
  415. * be centered around.
  416. * @var array
  417. */
  418. private $labels;
  419. /**
  420. * Constructor for axis. Sets the labels that should be used for the axis.
  421. * @param array $labels The key should be the distance in pixels along
  422. * the axis that the corresponding value should be centered around.
  423. * @param array $color An optional RGB color array representing the color
  424. * that the axis and its labels should have.
  425. */
  426. public function __construct($labels) {
  427. $this->labels = $labels;
  428. $this->displayGrid = false;
  429. }
  430. /**
  431. * Sets if grids should be used or not. One can also specify what color the
  432. * grid should be.
  433. * @param boolean $useGrids True if grids should eminate from the axis
  434. * wherever an label is displayed.
  435. * @param array $gridColor An optional RGB color array representing the
  436. * color that the grid should have. The default is black.
  437. */
  438. public function setGrid($useGrids) {
  439. $this->displayGrid = $useGrids;
  440. }
  441. /**
  442. * Draws the axis at a specified position in a specified image.
  443. * @param color $color The color that should be used to draw the axis.
  444. * @param color $gridColor the Color that should be used to draw the axis'
  445. * grids.
  446. * @param integer $startX The x coordinate where the axis should start.
  447. * @param integer $startY The y coordinate where the axis should start.
  448. * @param integer $endX The x coordinate where the axis should end.
  449. * @param integer $endY The y coordinate where the axis should end.
  450. */
  451. public function drawAxis(&$img, $color, $gridColor, $startX, $startY, $endX, $endY) {
  452. drawArrow($img, $startX, $startY, $endX, $endY,
  453. AXIS_POINT_LENGTH, AXIS_WIDTH, $color);
  454. //Draw the markers and grid
  455. if($this->displayGrid === true) {
  456. $markerLength = 1000;
  457. } else {
  458. $markerLength = AXIS_MARKER_SIZE;
  459. }
  460.  
  461. //Normalize the axis.
  462. $axisLength = sqrt(pow($endX - $startX, 2) + pow($endY - $startY, 2));
  463. $vNormalized = array(($endX - $startX)/$axisLength,
  464. ($endY - $startY)/$axisLength);
  465. //Create the normal of the axis for the markers and grid.
  466. if($endX == $startX) {
  467. //Avoid division by 0.
  468. $angle = pi()/2;
  469. } else {
  470. $angle = atan(($endY - $startY) / ($endX - $startX));
  471. }
  472. if($angle > pi()/4) {
  473. //Rotate pi/2 radians.
  474. $vNormal = array(-$vNormalized[1], $vNormalized[0]);
  475. } else {
  476. //Rotate -pi/2 radians.
  477. $vNormal = array($vNormalized[1], -$vNormalized[0]);
  478. }
  479.  
  480. $origo = array($startX, $startY);
  481. //Draw the markers, grid and labels.
  482. foreach($this->labels as $distance => $label) {
  483. $markerStart = $this->addVectors(
  484. $origo, $this->scaleVector($vNormalized, $distance));
  485. if(($markerStart[0] < $origo[0]) || ($markerStart[1] > $origo[1]) ||
  486. ($markerStart[0] > $endX) || ($markerStart[1] < $endY)) {
  487. continue;
  488. }
  489. $markerEnd = $this->addVectors($markerStart,
  490. $this->scaleVector($vNormal, $markerLength));
  491. if($angle > pi()/4) {
  492. drawStringRightAligned($img, 2, $markerStart[0], $markerStart[1]-7,
  493. $label, $color);
  494. } else {
  495. drawStringCentered($img, 2, $markerStart[0], $markerStart[1],
  496. $label, $color);
  497. }
  498. imageline($img, $markerStart[0], $markerStart[1], $markerEnd[0],
  499. $markerEnd[1], $gridColor);
  500. }
  501. }
  502. /**
  503. * Scales a specified vector with a specified scalar.
  504. * @param array $vector The vector to scale.
  505. * @param integer $scalar The scalar to scale with.
  506. * @return array A scaled vector.
  507. */
  508. private function scaleVector($vector, $scalar) {
  509. $result = array();
  510. foreach($vector as $key => $value) {
  511. $result[$key] = $value * $scalar;
  512. }
  513. return $result;
  514. }
  515. /**
  516. * Adds two of vectors.
  517. * @param array $vector1 The first vector to add.
  518. * @param array $vector2 The second vector to add.
  519. * @return array A vector sum.
  520. */
  521. private function addVectors($vector1, $vector2) {
  522. $result = $vector1;
  523. foreach($vector2 as $key => $value) {
  524. if(!isset($result[$key])) {
  525. $result[$key] = $value;
  526. } else {
  527. $result[$key] += $value;
  528. }
  529. }
  530. return $result;
  531. }
  532. }
  533.  
  534. /**
  535. * Describes a function that can be displayed in a graph.
  536. * @author Andreas Launila
  537. * @package com.lokorin.lokorin.lib
  538. */
  539. class GraphFunction {
  540. /**
  541. * The name that should represent the function. The name can be used to
  542. * identify the function.
  543. * @var string
  544. */
  545. private $name;
  546. /**
  547. * The values represent a strict function where the key is the function's
  548. * parameter and the corresponding value is the function's value for the
  549. * parameter. Both the parameters and key have to be numerical.
  550. * @var array
  551. */
  552. private $values;
  553. /**
  554. * Constructor for GraphFunction.
  555. * @param string $name The name of the function, this acts as an identifier
  556. * for the function and should hence be unique.
  557. * @param array $values The values that represent a strict function where
  558. * the key is the function's parameter and the corresponding value is
  559. * the function's value for the parameter. Both the parameters and key
  560. * have to be numerical.
  561. */
  562. public function __construct($name, $values) {
  563. $this->name = $name;
  564. $this->values = array();
  565. //Make sure that the function's key are integers.
  566. foreach($values as $key => $value) {
  567. $this->values[round($key)] = $value;
  568. }
  569. }
  570. /**
  571. * Gets the name of the function.
  572. * @return string A function name.
  573. */
  574. public function getName() {
  575. return $this->name;
  576. }
  577. /**
  578. * Gets the lowest value that is taken by the function.
  579. * @return integer A numerical value.
  580. */
  581. public function getLowestValue() {
  582. return min($this->values);
  583. }
  584. /**
  585. * Gets the highest value that is taken by the function.
  586. * @return integer A numerical value.
  587. */
  588. public function getHighestValue() {
  589. return max($this->values);
  590. }
  591. /**
  592. * Gets the lowest parameter that has a value in the function.
  593. * @return integer A numerical value.
  594. */
  595. public function getLowestParameter() {
  596. return min(array_keys($this->values));
  597. }
  598. /**
  599. * Gets the highest parameter that has a value in the function.
  600. * @return integer A numerical value.
  601. */
  602. public function getHighestParameter() {
  603. return max(array_keys($this->values));
  604. }
  605. /**
  606. * Draws the function at a specified position in a specified image.
  607. * @param image $image The image that the function should be drawn on.
  608. * @param color $color The color that should be used when drawing the
  609. * function, it has to have been allocated to the image.
  610. * @param integer $startX The x coordinate (pixels) where the function
  611. * should start.
  612. * @param integer $startY The y coordinate (pixels) where the function
  613. * should start.
  614. * @param integer $highestParam The highest parameter that should be drawn.
  615. * Any higher parameters should be clipped.
  616. * @param integer $lowestValue The lowest value that the function is
  617. * allowed to take on. Any values lower than this should be clipped.
  618. * @param integer $highestValue The highest value that the function is
  619. * allowed to take on. Any values higher than this should be clipped.
  620. * @param integer $scaleX The number of units that each pixel should
  621. * represent in x axis.
  622. * @param integer $scaleY The number of units that each pixel should
  623. * represent in y axis.
  624. */
  625. public function drawFunction(&$img, $color, $startX, $startY, $highestParam,
  626. $lowestValue, $highestValue, $scaleX, $scaleY) {
  627. $paramBase = min(array_keys($this->values));
  628. $height = imagesy($img) - $startY;
  629. $firstX = false;
  630. foreach($this->values as $x => $y) {
  631. //Fit them in the viewport
  632. if($x > $highestParam) {
  633. $x = $highestParam;
  634. }
  635. if($y < $lowestValue) {
  636. $y = $lowestValue;
  637. }
  638. if($firstX === false) {
  639. $firstX = $x;
  640. }
  641. $x -= $paramBase;
  642. //Invert the y coordinate.
  643. $y = ($height * $scaleY + $lowestValue) - $y;
  644. if(!isset($lastX) || !isset($lastY)) {
  645. $lastX = $x;
  646. $lastY = $y;
  647. continue;
  648. }
  649. imageline($img,
  650. $lastX / $scaleX + $startX,
  651. $lastY / $scaleY,
  652. $x / $scaleX + $startX,
  653. $y / $scaleY,
  654. $color
  655. );
  656. $lastX = $x;
  657. $lastY = $y;
  658. }
  659. //Draw the name of the function if there is one.
  660. if($this->name != '') {
  661. $middleX = round(($lastX + $firstX) / 2);
  662. if(!isset($this->values[$middleX])) {
  663. //Use the first parameter instead.
  664. $keys = array_keys($this->values);
  665. $middleX = $keys[current($this->values)];
  666. }
  667. $middleY = $height * $scaleY + $lowestValue - $this->values[$middleX];
  668. $middleX -= $paramBase;
  669. drawStringCentered($img, 2,
  670. $middleX / $scaleX + $startX,
  671. $middleY / $scaleY,
  672. $this->name, $color);
  673. }
  674. }
  675. }
  676.  
  677. ?>

Documentation generated on Sun, 16 Apr 2006 21:03:32 +0200 by phpDocumentor 1.3.0RC4