PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/gdgraph.php

https://github.com/Ixxy/Open-Affiliates
PHP | 1103 lines | 725 code | 138 blank | 240 comment | 188 complexity | 1dd51a7c6e65160b5b410f4e9e5cec2c MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. <?php
  2. /***********************************************************************************
  3. * Software: GDGraph *
  4. * Version: 2.1.0 *
  5. * Date: 2006-08-31 *
  6. * Author: Makko Solutions *
  7. * Contact: gdgraph@makko.com.mx *
  8. * License: GPL License (see below) *
  9. * Desription: Create line, pie and bar graphs with PHP and GD installed. *
  10. ***********************************************************************************/
  11. /***********************************************************************************
  12. * Copyright (C) 2006 Makko Solutions *
  13. * *
  14. * This program is free software; you can redistribute it and/or *
  15. * modify it under the terms of the GNU General Public License *
  16. * as published by the Free Software Foundation; either version 2 *
  17. * of the License, or (at your option) any later version. *
  18. * *
  19. * This program is distributed in the hope that it will be useful, *
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  22. * GNU General Public License for more details. *
  23. * *
  24. * You should have received a copy of the GNU General Public License *
  25. * along with this program; if not, write to the Free Software *
  26. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
  27. ***********************************************************************************/
  28. /*
  29. This software needs GD to be installed into PHP.
  30. Preferably the one bundled in, if it's PHP 4.3.0 or higher,
  31. since that's the one that it was made and tested with.
  32. */
  33. /*
  34. Corrections/Additions from 1.1.0:
  35. - Added the posibility to add 3D width to each bar of the bar graph.
  36. - Changed the way that line_graph shows a graph: it will now autoadjust to
  37. the values it has been given, showing more detail in the area in which
  38. there are values (kinda like autozoom), by putting asside the necessity
  39. of the x-axis always showing in it's 0 value. The X-axis will still always
  40. show, but it's now being dragged to up or down, depending of where the
  41. graph is being shown.
  42. - Because of the last point, it was a natural choice to give line_graph
  43. the possibility to indicate which area to zoom in on, from both the x-axis
  44. and the y-axis, dragging both of them as necessary. If this is done though,
  45. it's very probable that the x-axis will not always be at the y-axis origin.
  46. - Gave the y-axis in both bar and line graphs a dynamic x position, depending
  47. on the length of the y values.
  48. - Fixed some bugs concerning the way the bar and line graph were drawing.
  49. Corrections/Additions from 1.0.1:
  50. - Added the posibility to make the background transparent (not effective with
  51. Internet Explorer).
  52. - Added the posibility to change the surrounding line thickness and the line graph
  53. lines' thickness independently from each other.
  54. - Error in graphing the positive values of any graph when negative values
  55. existed.
  56. - Bug in _get_specs that didn't calculate correctly the max value of a line
  57. graph data array.
  58. - Added the option to the user to include or not the dots in the line graph.
  59. - Corrected many factors that made the line graph and bar graph put data
  60. outside the graph area, or waste too much space. Probably equivalent to a whole
  61. rewrite of both graph functions, but this new method is much faster, reliable and
  62. far more stable than the last one.
  63. - Added the possibility to create a grid in the line and bar graph,
  64. with the given option of how "dark" or "filled" the user wants the grid to be.
  65. - Fixed the fact that the argument that dictated the legend position was actually
  66. the top right corner of the legend not the documented top left corner.
  67. - Added the possibility to draw a border around the legend.
  68. - Added the possibility to add a 3D view to the pie graph, accepting a certain
  69. height for each slice, this has the potential to be used as another way to show
  70. another series of data in the same graph.
  71. - Changed the default of the pie graph function for it to occupy only 90% of the
  72. image, not 100%. This way, by default, the slice can be up to 30 pixels thick
  73. without being cut off from the image.
  74. - Added the possibility to rotate the pie graph giving a starting degree as a
  75. reference from which the whole graph will be drawn.
  76. - Added the option to draw or not the outline of the slices in the bar graph.
  77. - X Axis title switched to be printed above the X Axis (I know, I know, sorry...
  78. last time, I promise).
  79. Corrections from 1.0.0:
  80. - Fixed a neverending cycle when entering data arrays all with 0 values.
  81. - X Axis title switched to be printed below the X Axis.
  82. - Rounding error made the last value negative (in degrees) of pie data array.
  83. */
  84. if(!class_exists('GDGRAPH')){
  85. define('GDGRAPH_VERSION','2.1.0');
  86. class GDGraph{
  87. //Protected properties
  88. var $image; //actual image
  89. var $width; //width of whole image
  90. var $height; //height of whole image
  91. var $line_color; //color of surrounding lines
  92. var $line_thickness; //thickness of surrounding lines
  93. var $title; //title of graph
  94. var $bg_color; //background color
  95. var $bg_trans; //background transparency
  96. var $left_border; //distance from left border
  97. var $right_border; //distance from right border
  98. var $top_border; //distance from top border
  99. var $bottom_border; //distance from bottom border
  100. var $font_color; //font color
  101. var $legend; //if it's going to include a legend
  102. var $legend_border; //if it's going to print a border legend
  103. var $legend_x; //x position of legend
  104. var $legend_y; //y position of legend
  105. /****************** Public methods *******************/
  106. //Constructor.
  107. // Defaults:
  108. // With legend
  109. // With legend border
  110. // No titles
  111. // White solid (non-transparent) background
  112. // Black lines
  113. // Black font
  114. // 1 pixel thick lines.
  115. function GDGraph($w, $h, $t="", $bg_c_r=255, $bg_c_g=255, $bg_c_b=255, $l_c_r=0, $l_c_g=0, $l_c_b=0, $str_c_r=0, $str_c_g=0, $str_c_b=0, $l=true,$l_x=NULL,$l_y=NULL,$l_border=true,$trans_back=false, $l_thickness=1){
  116. $this->width = $w+0;
  117. $this->height = $h+0;
  118. if ($this->width <= 0 || $this->height <= 0){
  119. die("GDGraph Error: Width nor height can be smaller or equal to 0.");
  120. }
  121. $this->image = imagecreate($this->width, $this->height);
  122. $this->line_color = imagecolorallocate($this->image, ($l_c_r+0), ($l_c_g+0), ($l_c_b+0));
  123. $this->line_thickness = $l_thickness;
  124. $this->bg_color = imagecolorallocate($this->image, ($bg_c_r+0), ($bg_c_g+0), ($bg_c_b+0));
  125. $this->bg_trans = $trans_back;
  126. $this->font_color = imagecolorallocate($this->image, ($str_c_r+0), ($str_c_g+0), ($str_c_b+0));
  127. $this->title = $t."";
  128. $this->left_border = ceil($this->width * 0.05);
  129. $this->right_border = $this->width - $this->left_border;
  130. $this->top_border = ceil($this->height * 0.05);
  131. $this->bottom_border = $this->height - $this->top_border;
  132. $this->legend = ($l && true);
  133. $this->legend_border = ($l_border && true);
  134. $this->legend_x = $l_x;
  135. $this->legend_y = $l_y;
  136. //Activate background color
  137. imagefill($this->image, 0 ,0, $this->bg_color);
  138. //Activate transparency
  139. if ($this->bg_trans){
  140. imagecolortransparent($this->image, $this->bg_color);
  141. }
  142. //Activating line thickness
  143. imagesetthickness($this->image, $this->line_thickness);
  144. }
  145. //Line Graph.
  146. // Arrays format:
  147. // Data Array:
  148. // Name of line => (value in t1, value in t2, value in t3 ...)
  149. // Color Array:
  150. // Name of line => (red, green, blue)
  151. // X Axis Labels Array:
  152. // t1, t2, t3 ...
  153. // Line Thickness Array:
  154. // Name of line => thickness of line
  155. // Defaults:
  156. // Black, 1 pixel thick lines
  157. // No labels
  158. // No limits
  159. function line_graph($data, $color=Array(), $x_ls=Array(), $x_t="", $y_t="", $inc_dot=true, $l_t=Array(), $g_per=0, $x_rl=NULL, $x_ru=NULL, $y_rl=NULL, $y_ru=NULL){
  160. if((((!is_null($x_rl)) && (!is_null($x_ru))) && ($x_rl >= $x_ru)) || (((!is_null($y_rl)) && (!is_null($y_ru))) && ($y_rl >= $y_ru)))
  161. die("Lower ranges of either X or Y can't be greater or equal to their upper ranges.");
  162. //Acknowledging the line graph limits in the X axis
  163. //We start by the color array... this is the same thing we're going to do
  164. //with the t values of each line's data array
  165. if ((!is_null($x_rl)) && (!is_null($x_ru))){
  166. $x_ls = array_slice($x_ls,$x_rl,($x_ru-$x_rl+1));
  167. }else if(!is_null($x_rl)){
  168. $x_ls = array_slice($x_ls,$x_rl);
  169. }else if(!is_null($x_ru)){
  170. $x_ls = array_slice($x_ls,0,$x_ru+1);
  171. }
  172. //Now we do that with the data array
  173. if ((!is_null($x_rl)) && (!is_null($x_ru))){
  174. foreach($data as $prod => $sub_data)
  175. $data[$prod] = array_slice($sub_data,$x_rl,($x_ru-$x_rl+1));
  176. }else if(!is_null($x_rl)){
  177. foreach($data as $prod => $sub_data)
  178. $data[$prod] = array_slice($sub_data,$x_rl);
  179. }else if(!is_null($x_ru)){
  180. foreach($data as $prod => $sub_data)
  181. $data[$prod] = array_slice($sub_data,0,$x_ru+1);
  182. }
  183. //Obtain all the specs of the data from the array,
  184. //including the Y axis length in data value without extra bottom nor top
  185. $specs = $this->_get_specs($data,"line");
  186. //Acknowledging the line graph limits in the Y axis
  187. //this is done by overriding the max_value and min_value specs
  188. if(!is_null($y_ru))
  189. $specs['max_value'] = $y_ru;
  190. if(!is_null($y_rl))
  191. $specs['min_value'] = $y_rl;
  192. if($specs['max_value'] < $specs['min_value'])
  193. die("Lower ranges of either X or Y can't be greater or equal to their upper ranges.");
  194. //This next section is
  195. //guaranteeing a completely scalable graph independently if graphing .001 or 1000
  196. $y_axis_slength = 0;
  197. $all_down = false;
  198. $all_up = false;
  199. if (($specs['max_value'] == 0) && ($specs['min_value'] == 0)){
  200. $y_axis_length = 10;
  201. }else{
  202. $y_axis_length = $specs["max_value"]-$specs['min_value'];
  203. //Getting the exponent to expand the y-axis length to cover
  204. $y_dig = 0;
  205. $y_division_value = $y_axis_length;
  206. if ($y_axis_length < 1){
  207. while ($y_division_value < 1){
  208. $y_dig++;
  209. $y_division_value *= 10;
  210. }
  211. }else {
  212. $y_dig = 1;
  213. while ($y_division_value >= 10){
  214. $y_dig--;
  215. $y_division_value /= 10;
  216. }
  217. }
  218. $y_dec = 0;
  219. if((!is_null($y_rl)) || (!is_null($y_ru))){
  220. //if some range was imposed, we make sure it's exact
  221. $y_t_min = abs($specs["min_value"])."";
  222. $y_t_array = explode(".",$y_t_min,2);
  223. if(array_key_exists(1, $y_t_array))
  224. $y_t_min = $y_t_array[1]."";
  225. else
  226. $y_t_min = "";
  227. $y_t_max = abs($specs["max_value"])."";
  228. $y_t_array = explode(".",$y_t_max,2);
  229. if(array_key_exists(1, $y_t_array))
  230. $y_t_max = $y_t_array[1]."";
  231. else
  232. $y_t_max = "";;
  233. $y_dec = max(strlen($y_t_max),strlen($y_t_min));
  234. }
  235. $y_dig = pow(10,$y_dig+$y_dec);
  236. $y_axis_length = ceil(($specs["max_value"]*$y_dig)-($specs['min_value']*$y_dig))/$y_dig;
  237. $y_axis_slength = $y_axis_length-(ceil($specs['max_value']*$y_dig)/$y_dig);
  238. //After this, if no range was imposed:
  239. //If the numerical length of the y_axis is 3,124, y_axis_length is 3,200
  240. //if it's 0.002292, y_axis_length is 0.0023, which will become the real
  241. //numerical length of they y-axis
  242. //Setting some flags
  243. if ($specs['max_value'] > 0){
  244. if ($specs['min_value'] >= 0){
  245. $all_up = true;
  246. }
  247. }else{
  248. $all_down = true;
  249. }
  250. }
  251. //Obtaining Y axis division length in data value
  252. if (!($all_down) && !($all_up)){
  253. $y_dig = 0;
  254. $y_division_value = $y_axis_length;
  255. if ($y_axis_length < 1){
  256. while ($y_division_value < 1){
  257. $y_dig--;
  258. $y_division_value *= 10;
  259. }
  260. $y_dig--;
  261. }else {
  262. while ($y_division_value >= 10){
  263. $y_dig++;
  264. $y_division_value /= 10;
  265. }
  266. $y_dig--;
  267. }
  268. $y_division_value = $y_division_value * pow(10, $y_dig);
  269. }else
  270. $y_division_value = $y_axis_length/10;
  271. //If there are both negative and positive data, another y division
  272. //is going to be needed.
  273. if (!($all_down) && !($all_up) && (is_null($y_rl)) && (is_null($y_ru))){
  274. $y_axis_length += $y_division_value;
  275. $y_axis_slength += $y_division_value;
  276. }
  277. //Obtaining how many steps (going downward in the y axis) is the x-axis
  278. $x_axis_count = floor(($y_axis_length - $y_axis_slength)/$y_division_value);
  279. //Top and bottom of y-axis
  280. $y_axis_top = $this->top_border;
  281. $y_axis_bottom = $this->bottom_border;
  282. //Obtaining conversion factor from data to pixel count
  283. $conversion_factor = ($y_axis_bottom - $y_axis_top)/$y_axis_length;
  284. $y_division_mid = $y_division_value * ($y_axis_bottom - $y_axis_top)/$y_axis_length;
  285. //Obtaining max Y value
  286. if (!($all_down) && !($all_up) && (is_null($y_rl)) && (is_null($y_ru)))
  287. //Thanks to chris (chrego3-1 at yahoo dot fr) for this next line of code
  288. $max_y_value = ($x_axis_count+1) * ($y_division_value);
  289. else if(!($all_down) && !($all_up)){
  290. $x_axis_count--;
  291. $max_y_value = $specs["max_value"];
  292. }else
  293. $max_y_value = $specs["max_value"];
  294. $current_y_pos = $y_axis_top;
  295. $current_y_value = $max_y_value;
  296. //Defining dashed line style
  297. if($g_per){
  298. if($g_per > 10) $g_per = 10;
  299. else if($g_per < 0) $g_per = 0;
  300. $g_per = ($g_per*2)+80;
  301. $grid_style=array($this->line_color, $this->line_color);
  302. for($i=0; $i < 100-$g_per; $i++)
  303. array_push($grid_style, IMG_COLOR_TRANSPARENT);
  304. imagesetstyle($this->image, $grid_style);
  305. }
  306. $max_font_left_space = 0;
  307. //Painting the y-axis
  308. $line_count = 0;
  309. while($current_y_pos <= $y_axis_bottom){
  310. $font_left_space = strlen($current_y_value."")*5;
  311. if ($max_font_left_space < $font_left_space) $max_font_left_space = $font_left_space;
  312. if (!$all_down)
  313. $current_y_pos += $y_division_mid;
  314. if((($all_up) && ($line_count == ($x_axis_count-1))) || (!($all_up) && ($line_count == $x_axis_count))){
  315. if ($all_up || ((!$all_down) && (is_null($y_rl)) && (is_null($y_ru))))
  316. $current_y_value = 0; //to avoid PHP putting something like "1628E-90" instead of 0
  317. else
  318. $current_y_value -= $y_division_value;
  319. }else{
  320. $current_y_value -= $y_division_value;
  321. }
  322. if ($all_down)
  323. $current_y_pos += $y_division_mid;
  324. $line_count++;
  325. }
  326. $font_left_space = strlen($current_y_value."")*5;
  327. if ($max_font_left_space < $font_left_space) $max_font_left_space = $font_left_space;
  328. $y_axis_x = $this->left_border+(($max_font_left_space-20));
  329. imageline($this->image, $y_axis_x, $y_axis_top, $y_axis_x, $y_axis_bottom, $this->line_color);
  330. //Painting the y divisions
  331. $y_division_left = $y_axis_x-5;
  332. $y_division_right = $y_axis_x+5;
  333. $current_y_pos = $y_axis_top;
  334. $current_y_value = $max_y_value;
  335. $x_axis_y = 0;
  336. $x_axis_y_value=0;
  337. $line_count = 0;
  338. while($current_y_pos <= $y_axis_bottom){
  339. $font_left_space = strlen($current_y_value."")*5;
  340. imagestring($this->image, 1, $y_division_left-$font_left_space, $current_y_pos-4, $current_y_value."", $this->font_color);
  341. imageline($this->image, $y_division_left, $current_y_pos, $y_division_right, $current_y_pos, $this->line_color);
  342. if($g_per)
  343. imageline($this->image, $y_division_right, $current_y_pos, $this->right_border, $current_y_pos, IMG_COLOR_STYLED);
  344. if (!$all_down)
  345. $current_y_pos += $y_division_mid;
  346. if((($all_up) && ($line_count == ($x_axis_count-1))) || (!($all_up) && ($line_count == $x_axis_count))){
  347. $x_axis_y = $current_y_pos;
  348. if ($all_up || ((!$all_down) && (is_null($y_rl)) && (is_null($y_ru))))
  349. $current_y_value = 0; //to avoid PHP putting something like "1628E-90" instead of 0
  350. else
  351. $current_y_value -= $y_division_value;
  352. $x_axis_y_value = $current_y_value;
  353. }else{
  354. $current_y_value -= $y_division_value;
  355. }
  356. if ($all_down)
  357. $current_y_pos += $y_division_mid;
  358. $line_count++;
  359. }
  360. //If there are both negative and positive data, another y division
  361. //is going to be needed.
  362. if (!($all_down) && !($all_up)){
  363. $font_left_space = strlen($current_y_value."")*5;
  364. imagestring($this->image, 1, $y_division_left-$font_left_space, $current_y_pos-4, $current_y_value."", $this->font_color);
  365. imageline($this->image, $y_division_left, $current_y_pos, $y_division_right, $current_y_pos, $this->line_color);
  366. if($g_per)
  367. imageline($this->image, $y_division_right, $current_y_pos, $this->right_border, $current_y_pos, IMG_COLOR_STYLED);
  368. $line_count++;
  369. }
  370. //Painting the small the extra parts in the above and lower parts
  371. //of the Y axis
  372. imageline($this->image, $y_axis_x, $y_axis_top-($y_division_mid/8), $y_axis_x, $y_axis_top, $this->line_color);
  373. imageline($this->image, $y_axis_x, $y_axis_bottom, $y_axis_x, $y_axis_bottom+($y_division_mid/8), $this->line_color);
  374. //Getting the y position of the x axis
  375. if (!($x_axis_y)){
  376. if($all_down){
  377. $x_axis_y = $y_axis_top;
  378. }else{
  379. $x_axis_y = $y_axis_bottom;
  380. }
  381. }else if($x_axis_y > $y_axis_bottom){
  382. $x_axis_y = $y_axis_bottom;
  383. }
  384. //Painting X axis
  385. $x_axis_left = $y_axis_x;
  386. $x_axis_right = $this->right_border;
  387. imageline($this->image, $x_axis_left, $x_axis_y, $x_axis_right, $x_axis_y, $this->line_color);
  388. $x_axis_left = $y_division_right+10;
  389. //Reversing the array that contains the x axis labels so that they can be obtained by
  390. //the 'array_pop' PHP function in the right order
  391. $x_label = array_reverse($x_ls);
  392. //Painting each line
  393. $x_division_width = ($x_axis_right - $x_axis_left)/($specs['length']-1);
  394. foreach($data as $prod => $sub_data){
  395. $currentline_color = imagecolorallocate($this->image, ($color[$prod][0]+0), ($color[$prod][1]+0), ($color[$prod][2]+0));
  396. $currentline_thickness = (is_array($l_t[$prod])) ? (($l_t[$prod][0]+0)==0) ? 1 : $l_t[$prod] : (($l_t[$prod]+0)==0) ? 1 : $l_t[$prod];
  397. $current_x_pos = $x_axis_left;
  398. $past_x = -1;
  399. $past_y = -1;
  400. foreach($sub_data as $i => $value){
  401. if ($all_down)
  402. $currentpoint_rel_height = ($value-$specs['max_value']) * $conversion_factor;
  403. else if ($all_up)
  404. $currentpoint_rel_height = ($value-$specs['min_value']) * $conversion_factor;
  405. else
  406. $currentpoint_rel_height = ($value-$x_axis_y_value) * $conversion_factor;
  407. $currentpoint_real_height = $x_axis_y - $currentpoint_rel_height;
  408. if($inc_dot)
  409. imagefilledrectangle($this->image, $current_x_pos-2, $currentpoint_real_height-2, $current_x_pos+2, $currentpoint_real_height+2, $currentline_color);
  410. if ($past_x != -1){
  411. //Activating the currentline thickness
  412. imagesetthickness($this->image, $currentline_thickness);
  413. imageline($this->image, $past_x, $past_y, $current_x_pos, $currentpoint_real_height, $currentline_color);
  414. }
  415. if(strcmp($specs['ref_length'],$prod)==0){
  416. //Reseting thickness of surrounding lines
  417. imagesetthickness($this->image, $this->line_thickness);
  418. imageline($this->image, $current_x_pos, $x_axis_y+5, $current_x_pos, $x_axis_y-5, $this->line_color);
  419. if($g_per){
  420. imagesetstyle($this->image, $grid_style);
  421. imageline($this->image, $current_x_pos, $x_axis_y-5, $current_x_pos, $this->top_border, IMG_COLOR_STYLED);
  422. imageline($this->image, $current_x_pos, $x_axis_y+5, $current_x_pos, $this->bottom_border, IMG_COLOR_STYLED);
  423. }
  424. //Printing X axis label
  425. $label = array_pop($x_label);
  426. $font_left_space = strlen($label."")*5/2;
  427. imagestring($this->image, 1, $current_x_pos-$font_left_space, $x_axis_y+1, $label."", $this->font_color);
  428. }
  429. $past_x = $current_x_pos;
  430. $past_y = $currentpoint_real_height;
  431. $current_x_pos += $x_division_width;
  432. }
  433. }
  434. //Reseting thickness of surrounding lines
  435. imagesetthickness($this->image, $this->line_thickness);
  436. //Printing Title
  437. $font_left_space = (strlen($this->title)*7)/2;
  438. imagestring($this->image, 3, ($this->width/2)-($font_left_space), 0, $this->title, $this->font_color);
  439. //Printing Y Axis Title
  440. // imagestring($this->image, 2, $y_division_left-$max_font_left_space, 0, $y_t."", $this->font_color);
  441. imagestring($this->image, 2, 0, 0, $y_t."", $this->font_color);
  442. //Printing X Axis Title
  443. $font_left_space = strlen($x_t."")*6;
  444. imagestring($this->image, 2, $this->width-$font_left_space, $x_axis_y-12, $x_t."", $this->font_color);
  445. //Legend
  446. if($this->legend){
  447. if (count($color)>0)
  448. $this->_do_legend($color);
  449. else{
  450. $key = array_keys($data);
  451. foreach($key as $key => $value){
  452. $color[$value] = Array(0,0,0);
  453. }
  454. $this->_do_legend($color);
  455. }
  456. }
  457. //Return image
  458. header('Content-type: image/png');
  459. imagepng($this->image);
  460. imagedestroy($this->image);
  461. }
  462. //Bar Graph.
  463. // Array format:
  464. // Name of bar=> (value of bar, red, green, blue)
  465. // Defaults:
  466. // Bar width/Region width = 90%
  467. // Black color
  468. function bar_graph($data, $x_t="", $y_t="", $wi_p=90, $g_per=0, $b_ol=true){
  469. //Obtaining Y axis length in data value without extra bottom nor top
  470. $specs = $this->_get_specs($data,"bar");
  471. //This next section is
  472. //guaranteeing a completely scalable graph independently if graphing .001 or 1000
  473. $y_axis_slength = 0;
  474. $all_down = false;
  475. $all_up = false;
  476. if (($specs['max_value'] == 0) && ($specs['min_value'] == 0)){
  477. $y_axis_length = 10;
  478. $y_axis_slength = 0;
  479. }else{
  480. if ($specs['max_value'] > 0){
  481. $y_axis_length = $specs["max_value"];
  482. if ($specs['min_value'] < 0){
  483. $y_axis_length -= $specs['min_value'];
  484. }
  485. }else{
  486. $y_axis_length = abs($specs["min_value"]);
  487. }
  488. $y_dig = 0;
  489. $y_division_value = $y_axis_length;
  490. if ($y_axis_length < 1){
  491. while ($y_division_value < 1){
  492. $y_dig++;
  493. $y_division_value *= 10;
  494. }
  495. }else {
  496. $y_dig = 1;
  497. while ($y_division_value >= 10){
  498. $y_dig--;
  499. $y_division_value /= 10;
  500. }
  501. }
  502. $y_dig = pow(10,$y_dig+1);
  503. if ($specs['max_value'] > 0){
  504. if ($specs['min_value'] < 0){
  505. $y_axis_length = ceil(($specs["max_value"]*$y_dig)-($specs['min_value']*$y_dig))/$y_dig;
  506. $y_axis_slength = $y_axis_length-(ceil($specs['max_value']*$y_dig)/$y_dig);
  507. }else{
  508. $y_axis_length = ceil($specs["max_value"]*$y_dig)/$y_dig;
  509. $all_up = true;
  510. }
  511. }else{
  512. $y_axis_length = abs(floor($specs["min_value"]*$y_dig)/$y_dig);
  513. $y_axis_slength = $y_axis_length;
  514. $all_down = true;
  515. }
  516. //After this:
  517. //If the numerical length of the y_axis is 3,124, y_axis_length is 3,200
  518. //if it's 0.002292, y_axis_length is 0.0023, which will become the real
  519. //numerical length of they y-axis
  520. }
  521. //Obtaining Y axis division length in data value
  522. if (!($all_down) && !($all_up)){
  523. $y_dig = 0;
  524. $y_division_value = $y_axis_length;
  525. if ($y_axis_length < 1){
  526. while ($y_division_value < 1){
  527. $y_dig--;
  528. $y_division_value *= 10;
  529. }
  530. $y_dig--;
  531. }else {
  532. while ($y_division_value >= 10){
  533. $y_dig++;
  534. $y_division_value /= 10;
  535. }
  536. $y_dig--;
  537. }
  538. $y_division_value = $y_division_value * pow(10, $y_dig);
  539. }else
  540. $y_division_value = $y_axis_length/10;
  541. //If there are both negative and positive data, another y division
  542. //is going to be needed.
  543. if (!($all_down) && !($all_up)){
  544. $y_axis_length += $y_division_value;
  545. $y_axis_slength += $y_division_value;
  546. }
  547. //Obtaining how many steps (going downward in the y axis) is the x-axis
  548. $x_axis_count = floor(($y_axis_length - $y_axis_slength)/$y_division_value);
  549. //Top and bottom of y-axis
  550. $y_axis_top = $this->top_border;
  551. $y_axis_bottom = $this->bottom_border;
  552. //Obtaining conversion factor from data to pixel count
  553. $conversion_factor = ($y_axis_bottom - $y_axis_top)/$y_axis_length;
  554. $y_division_mid = $y_division_value * ($y_axis_bottom - $y_axis_top)/$y_axis_length;
  555. //Obtaining max Y value
  556. if ($all_down)
  557. $max_y_value = 0;
  558. else if(!($all_down) && !($all_up)){
  559. //Thanks to chris (chrego3-1 at yahoo dot fr) for this next line of code
  560. $max_y_value = ($x_axis_count+1) * ($y_division_value);
  561. }else
  562. $max_y_value = $specs["max_value"];
  563. //Defining dashed line style
  564. if($g_per){
  565. if($g_per > 10) $g_per = 10;
  566. else if($g_per < 0) $g_per = 0;
  567. $g_per = ($g_per*2)+80;
  568. $style=array($this->line_color, $this->line_color);
  569. for($i=0; $i < 100-$g_per; $i++)
  570. array_push($style, IMG_COLOR_TRANSPARENT);
  571. imagesetstyle($this->image, $style);
  572. }
  573. $current_y_pos = $y_axis_top;
  574. $current_y_value = $max_y_value;
  575. $max_font_left_space = 0;
  576. //Painting the y-axis
  577. $line_count = 0;
  578. while($current_y_pos <= $y_axis_bottom){
  579. $font_left_space = strlen($current_y_value."")*5;
  580. if ($max_font_left_space < $font_left_space) $max_font_left_space = $font_left_space;
  581. if (!$all_down)
  582. $current_y_pos += $y_division_mid;
  583. if($line_count == ($x_axis_count-1)){
  584. $x_axis_y = $current_y_pos;
  585. if (!$all_down){
  586. $current_y_value = 0; //to avoid PHP putting something like "1628E-90" instead of 0
  587. }else
  588. $current_y_value -= $y_division_value;
  589. }else{
  590. $current_y_value -= $y_division_value;
  591. }
  592. if ($all_down)
  593. $current_y_pos += $y_division_mid;
  594. $line_count++;
  595. }
  596. $font_left_space = strlen($current_y_value."")*5;
  597. if ($max_font_left_space < $font_left_space) $max_font_left_space = $font_left_space;
  598. $y_axis_x = $this->left_border+(($max_font_left_space));
  599. imageline($this->image, $y_axis_x, $y_axis_top, $y_axis_x, $y_axis_bottom, $this->line_color);
  600. //Painting y-divisions
  601. $y_division_left = $y_axis_x-5;
  602. $y_division_right = $y_axis_x+5;
  603. $current_y_pos = $y_axis_top;
  604. $current_y_value = $max_y_value;
  605. $x_axis_y = 0;
  606. $x_axis_y_value=0;
  607. $line_count = 0;
  608. while($current_y_pos <= $y_axis_bottom){
  609. $font_left_space = strlen($current_y_value."")*5;
  610. imagestring($this->image, 1, $y_division_left-$font_left_space, $current_y_pos-4, $current_y_value."", $this->font_color);
  611. imageline($this->image, $y_division_left, $current_y_pos, $y_division_right, $current_y_pos, $this->line_color);
  612. if($g_per) {
  613. imagesetstyle($this->image, $style);
  614. imageline($this->image, $y_division_right, $current_y_pos, $this->right_border, $current_y_pos, IMG_COLOR_STYLED);
  615. }
  616. if (!$all_down)
  617. $current_y_pos += $y_division_mid;
  618. // if((($all_up) && ($line_count == ($x_axis_count-1))) || (!($all_up) && ($line_count == $x_axis_count))){
  619. if($line_count == $x_axis_count){
  620. $x_axis_y = $current_y_pos;
  621. if (!$all_down)
  622. $current_y_value = 0; //to avoid PHP putting something like "1628E-90" instead of 0
  623. else
  624. $current_y_value -= $y_division_value;
  625. }else{
  626. $current_y_value -= $y_division_value;
  627. }
  628. if ($all_down)
  629. $current_y_pos += $y_division_mid;
  630. $line_count++;
  631. }
  632. $max_font_left_space = 0;
  633. //If there are both negative and positive data, another y division
  634. //is going to be needed.
  635. if (!($all_down) && !($all_up)){
  636. $font_left_space = strlen($current_y_value."")*5;
  637. imagestring($this->image, 1, $y_division_left-$font_left_space, $current_y_pos-4, $current_y_value."", $this->font_color);
  638. imageline($this->image, $y_division_left, $current_y_pos, $y_division_right, $current_y_pos, $this->line_color);
  639. if($g_per)
  640. imageline($this->image, $y_division_right, $current_y_pos, $this->right_border, $current_y_pos, IMG_COLOR_STYLED);
  641. $line_count++;
  642. if ($max_font_left_space < $font_left_space) $max_font_left_space = $font_left_space;
  643. }
  644. //Painting the small the extra parts in the above and lower parts
  645. //of the Y axis
  646. imageline($this->image, $y_axis_x, $y_axis_top-($y_division_mid/8), $y_axis_x, $y_axis_top, $this->line_color);
  647. imageline($this->image, $y_axis_x, $y_axis_bottom, $y_axis_x, $y_axis_bottom+($y_division_mid/8), $this->line_color);
  648. //Obtaining the y position of the x axis
  649. if (!($x_axis_y)){
  650. if($all_down){
  651. $x_axis_y = $y_axis_top;
  652. }else{
  653. $x_axis_y = $y_axis_bottom;
  654. }
  655. }else if($x_axis_y > $y_axis_bottom){
  656. $x_axis_y = $y_axis_bottom;
  657. }
  658. //Painting X axis
  659. $x_axis_left = $y_division_right;
  660. $x_axis_right = $this->right_border;
  661. imageline($this->image, $x_axis_left, $x_axis_y, $x_axis_right, $x_axis_y, $this->line_color);
  662. //Painting each bar
  663. $bar_width = ($x_axis_right - $x_axis_left)/count($data);
  664. $bar_side_space = $bar_width*((100-abs($wi_p))/200);
  665. $current_x_pos = $x_axis_right - $bar_width;
  666. $data_rev = array_reverse($data);
  667. foreach($data_rev as $prod => $sub_data){
  668. $currentbar_rel_height = $sub_data[0] * $conversion_factor;
  669. $currentbar_color = imagecolorallocate($this->image, ($sub_data[1]+0), ($sub_data[2]+0), ($sub_data[3]+0));
  670. $currentbar_3dcolor = imagecolorallocate($this->image, ($sub_data[1]-50 < 0) ? 0 : $sub_data[1]-50, ($sub_data[2]-50 < 0) ? 0 : $sub_data[2]-50, ($sub_data[3]-50 < 0) ? 0 : $sub_data[3]-50);
  671. $currentbar_3dwidth = (array_key_exists(4,$sub_data)) ? $sub_data[4]+0 : 0;
  672. $currentbar_varedge = $x_axis_y-$currentbar_rel_height;
  673. if ($currentbar_varedge > $x_axis_y){
  674. //3D Effect
  675. for($i = 0; $i < $currentbar_3dwidth; $i++)
  676. imagefilledrectangle($this->image, $current_x_pos+$bar_side_space+$i, $x_axis_y+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $currentbar_varedge+$i, $currentbar_3dcolor);
  677. imagefilledrectangle($this->image, $current_x_pos+$bar_side_space+$i, $x_axis_y+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $currentbar_varedge+$i, $currentbar_color);
  678. if($b_ol){
  679. imagepolygon($this->image,Array(
  680. $current_x_pos+$bar_side_space, $x_axis_y,
  681. $current_x_pos+$bar_width-$bar_side_space,$x_axis_y,
  682. $current_x_pos+$bar_width-$bar_side_space+$i,$x_axis_y+$i,
  683. $current_x_pos+$bar_side_space+$i,$x_axis_y+$i
  684. ),4,$this->line_color);
  685. imagepolygon($this->image,Array(
  686. $current_x_pos+$bar_side_space, $x_axis_y,
  687. $current_x_pos+$bar_side_space+$i,$x_axis_y+$i,
  688. $current_x_pos+$bar_side_space+$i,$currentbar_varedge+$i,
  689. $current_x_pos+$bar_side_space,$currentbar_varedge
  690. ),4,$this->line_color);
  691. imagerectangle($this->image, $current_x_pos+$bar_side_space+$i, $x_axis_y+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $currentbar_varedge+$i, $this->line_color);
  692. }
  693. }else{
  694. //3D Effect
  695. for($i = 0; $i < $currentbar_3dwidth; $i++)
  696. imagefilledrectangle($this->image, $current_x_pos+$bar_side_space+$i, $currentbar_varedge+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $x_axis_y+$i, $currentbar_3dcolor);
  697. imagefilledrectangle($this->image, $current_x_pos+$bar_side_space+$i, $currentbar_varedge+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $x_axis_y+$i, $currentbar_color);
  698. if($b_ol){
  699. imagepolygon($this->image,Array(
  700. $current_x_pos+$bar_side_space, $currentbar_varedge,
  701. $current_x_pos+$bar_width-$bar_side_space, $currentbar_varedge,
  702. $current_x_pos+$bar_width-$bar_side_space+$i, $currentbar_varedge+$i,
  703. $current_x_pos+$bar_side_space+$i, $currentbar_varedge+$i
  704. ),4,$this->line_color);
  705. imagepolygon($this->image,Array(
  706. $current_x_pos+$bar_side_space, $x_axis_y,
  707. $current_x_pos+$bar_side_space+$i,$x_axis_y+$i,
  708. $current_x_pos+$bar_side_space+$i,$currentbar_varedge+$i,
  709. $current_x_pos+$bar_side_space,$currentbar_varedge
  710. ),4,$this->line_color);
  711. imagerectangle($this->image, $current_x_pos+$bar_side_space+$i, $x_axis_y+$i, $current_x_pos+$bar_width-$bar_side_space+$i, $currentbar_varedge+$i, $this->line_color);
  712. }
  713. }
  714. $font_left_space = (strlen($prod)*5)/2;
  715. if(is_string($prod)) {
  716. imagestring($this->image, 2, $current_x_pos+($bar_width/2)-($font_left_space)+$i, $x_axis_y+$i, $prod, $this->font_color);
  717. }
  718. $current_x_pos -= $bar_width;
  719. }
  720. //Printing Title
  721. $font_left_space = (strlen($this->title)*7)/2;
  722. imagestring($this->image, 3, ($this->width/2)-($font_left_space), 0, $this->title, $this->font_color);
  723. //Printing Y Axis Title
  724. imagestring($this->image, 2, $y_division_left-$max_font_left_space, 0, $y_t."", $this->font_color);
  725. //Printing X Axis Title
  726. $font_left_space = strlen($x_t."")*6;
  727. imagestring($this->image, 2, $this->width-$font_left_space, $x_axis_y-12, $x_t."", $this->font_color);
  728. //Printing Legend
  729. if($this->legend){
  730. $legend_data = Array();
  731. foreach($data as $prod => $sub_data){
  732. $legend_data[$prod] = Array($sub_data[1],$sub_data[2],$sub_data[3]);
  733. }
  734. $this->_do_legend($legend_data);
  735. }
  736. //Return image
  737. header('Content-type: image/png');
  738. imagepng($this->image);
  739. imagedestroy($this->image);
  740. }
  741. //Pie Graph.
  742. // Array format:
  743. // Name of pie slice => (absolute value of slice, red, green, blue)
  744. // Defaults:
  745. // Black color
  746. // Pie filling 90% of the image
  747. // With piece labels
  748. // Start at 0 degrees
  749. // No 3D effect in anyone
  750. // 1 pixel line thickness
  751. function pie_graph($data, $p_o=90, $put_pieces=true, $degree_start=0, $put_l=true, $threed_thickness=Array()){
  752. //Get center of pie
  753. $pie_center_x = ($this->right_border + $this->left_border)/2;
  754. $pie_center_y = ($this->top_border + $this->bottom_border)/2;
  755. $pie_width = ($this->right_border - $this->left_border)*$p_o/100;
  756. $pie_height = ($this->bottom_border - $this->top_border)*$p_o/100;
  757. //Draw lines, fill with color and label each pie slice
  758. $specs = $this->_get_specs($data,"pie");
  759. $data_total_elements = count($data);
  760. $max_threed_thickness = 0;
  761. if (count($threed_thickness) > 0){
  762. $max_threed_thickness = max($threed_thickness)+0;
  763. }
  764. for ($i = 0; $i <= $max_threed_thickness; $i++){
  765. $total_degree_width = 0;
  766. $curr_ele = 1;
  767. foreach($data as $prod => $subarray){
  768. //Getting degree width of slice
  769. if ($curr_ele == $data_total_elements){
  770. $degree_width = 360 - $total_degree_width;
  771. //Thanks for Nam Phando for this next three lines.
  772. //The last value of the array can have a negative value
  773. //because of rounding errors, so these takes care of it.
  774. if ($degree_width < 0){
  775. $degree_width = 0;
  776. }
  777. }else{
  778. //Usage of round, recommended by Nam Phando.
  779. $degree_width = round((($subarray[0]+0) / $specs['total'])*360);
  780. }
  781. $curr_ele++;
  782. if ($i == $threed_thickness[$prod]+0){
  783. //Obtaining the color of this slice
  784. $curr_color = imagecolorallocate($this->image,$subarray[1]+0,$subarray[2]+0,$subarray[3]+0);
  785. //Drawing slice with its color
  786. imagefilledarc($this->image, $pie_center_x, $pie_center_y-$threed_thickness[$prod], $pie_width, $pie_height, $degree_start+$total_degree_width, $degree_start+$total_degree_width+$degree_width, $curr_color,IMG_ARC_PIE);
  787. //Drawing top outline and side outline
  788. if($put_l){
  789. imagefilledarc($this->image, $pie_center_x, $pie_center_y-$threed_thickness[$prod], $pie_width, $pie_height, $degree_start+$total_degree_width, $degree_start+$total_degree_width+$degree_width, $this->line_color,IMG_ARC_NOFILL | IMG_ARC_EDGED);
  790. if ((floor(($degree_start+$total_degree_width)/180)%2) == 0){
  791. $ver_line_pos = $this->_ellipse_pos($degree_start+$total_degree_width, $pie_height, $pie_width, "");
  792. imageline($this->image, $pie_center_x+$ver_line_pos['x'], $pie_center_y+$ver_line_pos['y'], $pie_center_x+$ver_line_pos['x'], $pie_center_y+$ver_line_pos['y']-$threed_thickness[$prod], $this->line_color);
  793. }
  794. if ((floor(($degree_start+$total_degree_width+$degree_width)/180)%2) == 0){
  795. $ver_line_pos = $this->_ellipse_pos($degree_start+$total_degree_width+$degree_width, $pie_height, $pie_width, "");
  796. imageline($this->image, $pie_center_x+$ver_line_pos['x'], $pie_center_y+$ver_line_pos['y'], $pie_center_x+$ver_line_pos['x'], $pie_center_y+$ver_line_pos['y']-$threed_thickness[$prod], $this->line_color);
  797. }
  798. }
  799. //Printing label
  800. if($put_pieces){
  801. $label_pos = $this->_ellipse_pos($degree_start+$total_degree_width+($degree_width/2), $pie_height, $pie_width, $prod."");
  802. imagestring($this->image, 2, $pie_center_x+$label_pos['x'], $pie_center_y+$label_pos['y']-$threed_thickness[$prod], $prod."", $this->font_color);
  803. }
  804. }else if ($i < $threed_thickness[$prod]+0){
  805. //Obtaining the color of the 3D side of this slice
  806. $curr_3dcolor = imagecolorallocate($this->image, ($subarray[1]-50 < 0) ? 0 : $subarray[1]-50, ($subarray[2]-50 < 0) ? 0 : $subarray[2]-50, ($subarray[3]-50 < 0) ? 0 : $subarray[3]-50);
  807. //Drawing bottom outline of pie in 3d
  808. if($put_l and $i == 0)
  809. imagefilledarc($this->image, $pie_center_x, $pie_center_y, $pie_width+1, $pie_height+1, $degree_start+$total_degree_width, $degree_start+$total_degree_width+$degree_width, $this->line_color,IMG_ARC_NOFILL | IMG_ARC_EDGED);
  810. //Creating 3D effect
  811. imagefilledarc($this->image, $pie_center_x, $pie_center_y-$i, $pie_width, $pie_height, $degree_start+$total_degree_width, $degree_start+$total_degree_width+$degree_width, $curr_3dcolor,IMG_ARC_PIE);
  812. }
  813. //Getting starting point of next slice
  814. $total_degree_width+=$degree_width;
  815. }
  816. }
  817. //Printing title
  818. $font_left_space = (strlen($this->title)*7)/2;
  819. imagestring($this->image, 3, ($this->width/2)-($font_left_space), 0, $this->title, $this->font_color);
  820. //Printing legend
  821. if($this->legend){
  822. $legend_data = Array();
  823. foreach($data as $prod => $sub_data){
  824. $legend_data[$prod] = Array($sub_data[1],$sub_data[2],$sub_data[3]);
  825. }
  826. $this->_do_legend($legend_data);
  827. }
  828. //Return image
  829. header('Content-type: image/png');
  830. imagepng($this->image);
  831. imagedestroy($this->image);
  832. }
  833. /****************** Protected methods *******************/
  834. //Gets the highest value, lowest value, and average out of an array.
  835. function _get_specs($data, $type){
  836. switch($type){
  837. case "line":
  838. $longest = 0;
  839. $longest_index = "";
  840. //Thanks to Mathieu Davy for detecting the absence of this next line
  841. $max = $data[key($data)][0];
  842. $min = $data[key($data)][0]; //get the first element to search for
  843. //lowest and highest value
  844. foreach($data as $i => $sub_array){
  845. $this_max = max($sub_array);
  846. $this_min = min($sub_array);
  847. $length = count($sub_array);
  848. if($max < $this_max){
  849. $max = $this_max;
  850. }
  851. if($min > $this_min){
  852. $min = $this_min;
  853. }
  854. if($longest < $length){
  855. $longest = $length;
  856. $longest_index = $i;
  857. }
  858. }
  859. return Array("max_value" => $max,"min_value" => $min, "length" => $longest, "ref_length" => $longest_index);
  860. case "bar":
  861. $max = $data[key($data)][0];
  862. $min = $data[key($data)][0]; //get the first element to search for
  863. //lowest and highest value
  864. foreach($data as $i => $sub_array){
  865. if($max < $sub_array[0]){
  866. $max = $sub_array[0];
  867. }
  868. if($min > $sub_array[0]){
  869. $min = $sub_array[0];
  870. }
  871. }
  872. return Array("max_value" => $max,"min_value" => $min);
  873. case "pie":
  874. $total = 0;
  875. foreach($data as $i => $sub_array){
  876. $total += $sub_array[0];
  877. }
  878. return Array("total" => $total);
  879. break;
  880. }
  881. }
  882. //Displays the legend
  883. // Array format:
  884. // Name => (red, green, blue)
  885. function _do_legend($data){
  886. //Getting the width and height of the legend
  887. $longest_name_length = 0;
  888. $legend_height = 0;
  889. foreach($data as $name => $sub_data){
  890. if (strlen($name) > $longest_name_length) $longest_name_length = strlen($name);
  891. $legend_height += 10;
  892. }
  893. $legend_width = ($longest_name_length*5)+18;
  894. //Getting the x position of the left corner of the legend
  895. if (($this->legend_x > $this->right_border) || is_null($this->legend_x))
  896. $this->legend_x = $this->right_border - $legend_width;
  897. else if ($this->legend_x < $this->left_border)
  898. $this->legend_x = $this->left_border;
  899. $current_x_pos = $this->legend_x;
  900. //Getting the y position of the left corner of the legend
  901. if (($this->legend_y < ($this->top_border)) || is_null($this->legend_y))
  902. $this->legend_y = $this->top_border;
  903. else if ($this->legend_y > $this->bottom_border - $legend_height)
  904. $this->legend_y = $this->bottom_border - $legend_height;
  905. $current_y_pos = $this->legend_y + 1;
  906. //Printing the titles and colors of the data
  907. foreach($data as $name => $sub_data){
  908. $current_color = imagecolorallocate($this->image, ($sub_data[0]+0), ($sub_data[1]+0), ($sub_data[2]+0));
  909. imagefilledrectangle($this->image, $current_x_pos+3,$current_y_pos+1, $current_x_pos+8,$current_y_pos+6,$current_color);
  910. imagestring($this->image, 1, $current_x_pos+16, $current_y_pos, $name, $this->font_color);
  911. $current_y_pos += 10;
  912. }
  913. //Printing legend border
  914. if($this->legend_border)
  915. imagerectangle($this->image, $this->legend_x, $this->legend_y, $this->legend_x+$legend_width, $this->legend_y+$legend_height, $this->line_color);
  916. }
  917. //Returns the true position of a label given the height, width and radius of an ellipse
  918. function _ellipse_pos($degree, $ellipse_height, $ellipse_width, $prod){
  919. //Obtaining segments a and b from ellipse
  920. $ellipse_a = ceil($ellipse_width/2);
  921. $ellipse_b = ceil($ellipse_height/2);
  922. $ellipse_a2 = pow($ellipse_a,2);
  923. $ellipse_b2 = pow($ellipse_b,2);
  924. //Proportion from this ellipse between x and y
  925. $e = $ellipse_height/$ellipse_width;
  926. $circle_radius = ($ellipse_height > $ellipse_width) ? $ellipse_height : $ellipse_width;
  927. //Obtaining Y of the circle from which this ellipse was squished from
  928. $circle_angle_x = $circle_radius*cos(deg2rad($degree));
  929. $circle_angle_y = $circle_radius*sin(deg2rad($degree));
  930. if ($ellipse_height > $ellipse_width){
  931. //Obtaining x for this ellipse, because we know that if we're here, $circle_angle_y == $label_y
  932. $circle_angle_x = $circle_angle_x/$e;
  933. }else{
  934. //Obtaining y for this ellipse, because we know that if we're here, $circle_angle_x == $label_x
  935. $circle_angle_y = $circle_angle_y*$e;
  936. }
  937. $label_angle = rad2deg(atan($circle_angle_y/$circle_angle_x));
  938. if($circle_angle_y < 0 && $circle_angle_x < 0){
  939. $label_angle += 180;
  940. }else if($circle_angle_y < 0){
  941. $label_angle = 360 + $label_angle;
  942. }else if($circle_angle_x < 0){
  943. $label_angle += 180;
  944. }
  945. $label_radius = round(sqrt($ellipse_b2*$ellipse_a2/(($ellipse_b2*pow(cos(deg2rad($label_angle)),2))+($ellipse_a2*pow(sin(deg2rad($label_angle)),2)))));
  946. if (strlen($prod."") > 0){
  947. if($label_angle > 90 && $label_angle < 180){
  948. $label_radius += (abs(strlen($prod."")*3)*abs(sin(deg2rad($label_angle-90))));
  949. }else if($label_angle >= 180 && $label_angle <= 270){
  950. $label_radius += (abs(strlen($prod."")*3)*abs(sin(deg2rad($label_angle-90))))+(10*abs(sin(0.5*deg2rad($label_angle))));
  951. }else if($label_angle > 270){
  952. $label_radius -= (abs(strlen($prod."")*3/2)*abs(sin(deg2rad($label_angle-90))));
  953. }
  954. }
  955. return Array('x' => $label_radius*cos(deg2rad($label_angle)), 'y' => $label_radius*sin(deg2rad($label_angle)));
  956. }
  957. }}
  958. ?>