PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/newgraph.php

https://github.com/csmith/WeightTracker
PHP | 319 lines | 256 code | 55 blank | 8 comment | 52 complexity | 58f94412926757fd01e418b055f0e392 MD5 | raw file
  1. <?PHP
  2. function imagesmoothline ( $image , $x1 , $y1 , $x2 , $y2 , $color )
  3. {
  4. $colors = imagecolorsforindex ( $image , $color );
  5. if ( $x1 == $x2 )
  6. {
  7. imageline ( $image , $x1 , $y1 , $x2 , $y2 , $color ); // Vertical line
  8. }
  9. else
  10. {
  11. $m = ( $y2 - $y1 ) / ( $x2 - $x1 );
  12. $b = $y1 - $m * $x1;
  13. if ( abs ( $m ) <= 1 )
  14. {
  15. $x = min ( $x1 , $x2 );
  16. $endx = max ( $x1 , $x2 );
  17. while ( $x <= $endx )
  18. {
  19. $y = $m * $x + $b;
  20. $y == floor ( $y ) ? $ya = 1 : $ya = $y - floor ( $y );
  21. $yb = ceil ( $y ) - $y;
  22. $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , $x , floor ( $y ) ) );
  23. $tempcolors['red'] = $tempcolors['red'] * $ya + $colors['red'] * $yb;
  24. $tempcolors['green'] = $tempcolors['green'] * $ya + $colors['green'] * $yb;
  25. $tempcolors['blue'] = $tempcolors['blue'] * $ya + $colors['blue'] * $yb;
  26. if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
  27. imagesetpixel ( $image , $x , floor ( $y ) , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
  28. $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , $x , ceil ( $y ) ) );
  29. $tempcolors['red'] = $tempcolors['red'] * $yb + $colors['red'] * $ya;
  30. $tempcolors['green'] = $tempcolors['green'] * $yb + $colors['green'] * $ya;
  31. $tempcolors['blue'] = $tempcolors['blue'] * $yb + $colors['blue'] * $ya;
  32. if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
  33. imagesetpixel ( $image , $x , ceil ( $y ) , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
  34. $x ++;
  35. }
  36. }
  37. else
  38. {
  39. $y = min ( $y1 , $y2 );
  40. $endy = max ( $y1 , $y2 );
  41. while ( $y <= $endy )
  42. {
  43. $x = ( $y - $b ) / $m;
  44. $x == floor ( $x ) ? $xa = 1 : $xa = $x - floor ( $x );
  45. $xb = ceil ( $x ) - $x;
  46. $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , floor ( $x ) , $y ) );
  47. $tempcolors['red'] = $tempcolors['red'] * $xa + $colors['red'] * $xb;
  48. $tempcolors['green'] = $tempcolors['green'] * $xa + $colors['green'] * $xb;
  49. $tempcolors['blue'] = $tempcolors['blue'] * $xa + $colors['blue'] * $xb;
  50. if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
  51. imagesetpixel ( $image , floor ( $x ) , $y , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
  52. $tempcolors = imagecolorsforindex ( $image , imagecolorat ( $image , ceil ( $x ) , $y ) );
  53. $tempcolors['red'] = $tempcolors['red'] * $xb + $colors['red'] * $xa;
  54. $tempcolors['green'] = $tempcolors['green'] * $xb + $colors['green'] * $xa;
  55. $tempcolors['blue'] = $tempcolors['blue'] * $xb + $colors['blue'] * $xa;
  56. if ( imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) == -1 ) imagecolorallocate ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] );
  57. imagesetpixel ( $image , ceil ( $x ) , $y , imagecolorexact ( $image , $tempcolors['red'] , $tempcolors['green'] , $tempcolors['blue'] ) );
  58. $y ++;
  59. }
  60. }
  61. }
  62. }
  63. function array_min($array) {
  64. $min = 9999999999;
  65. foreach ($array as $v) { $min = min($v, $min); }
  66. return $min;
  67. }
  68. require_once('data.php');
  69. define('GWIDTH', 800);
  70. define('GHEIGHT', 792);
  71. $maxtweek = 0; $mintbmi = 100;
  72. foreach ($targets as $target) {
  73. list($week, $bmi) = $target;
  74. $maxtweek = max($week - 1, $maxtweek);
  75. $mintbmi = min($mintbmi, $bmi);
  76. }
  77. $mintmass = $mintbmi * HEIGHT * HEIGHT;
  78. define('XMIN', 0);
  79. define('XMAX', max($maxtweek + 1, count($data)));
  80. define('YMIN', ~1 & min($mintmass, floor(array_min($data)) - 10));
  81. define('YMAX', 140);
  82. $im = imagecreate(GWIDTH, GHEIGHT);
  83. $black = imagecolorallocate($im, 0x00, 0x00, 0x00);
  84. $grey = imagecolorallocate($im, 0x66, 0x66, 0x66);
  85. $white = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);
  86. $red = imagecolorallocate($im, 0xAA, 0x33, 0x33);
  87. imagefill($im, 0, 0, $white);
  88. //imagerectangle($im, 0, 0, GWIDTH - 1, GHEIGHT - 1, $black);
  89. //imagefilledrectangle($im, 0, 0, GWIDTH - 1, 60, $black);
  90. imagerectangle($im, 65, 45, GWIDTH - 55, GHEIGHT - 45, $black);
  91. function dashLine($im, $y, $colour) {
  92. $n = 3;
  93. for ($i = 69; $i < GWIDTH - 59; $i += $n) {
  94. imageline($im, $i, $y, $i, $y, $colour);
  95. $n = 1 + ceil((($i - 60) / 3) / 20);
  96. }
  97. }
  98. function dashLine2($im, $y, $colour) {
  99. $n = 3;
  100. for ($i = GWIDTH - 59; $i > 69; $i -= $n) {
  101. imageline($im, $i, $y, $i, $y, $colour);
  102. $n = 1 + ceil(((GWIDTH - ($i + 59)) / 3) / 20);
  103. }
  104. }
  105. function fillBMI($im, $min, $max, $colour, $label) {
  106. $omin = $min; $omax = $max;
  107. $min = min(YMAX, max(YMIN, $min * HEIGHT * HEIGHT));
  108. $max = max(YMIN, min(YMAX, $max * HEIGHT * HEIGHT));
  109. if ($min == $max) { return; }
  110. $y1 = GHEIGHT - 45 - ($min - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  111. $y2 = GHEIGHT - 45 - ($max - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  112. imagefilledrectangle($im, 66, $max == YMAX ? $y2 + 1 : $y2, GWIDTH - 56, $y1 - 1, $colour);
  113. imageline($im, 66, $y2, GWIDTH - 56, $y2, imagecolorallocate($im, 0x00, 0x00, 0x00));
  114. $bmi = $omax == 100 ? "$omin+" : "$omin-$omax";
  115. imagestring($im, 1, 69, $y2 + 3, "BMI $bmi: '$label'", $black);
  116. }
  117. $colours = array(
  118. imagecolorallocate($im, 0xFF, 0xFF, 0xFF),
  119. imagecolorallocate($im, 0xE0, 0xFF, 0xFF),
  120. imagecolorallocate($im, 0xC0, 0xDE, 0xEC),
  121. imagecolorallocate($im, 0x87, 0xCE, 0xFA),
  122. imagecolorallocate($im, 0x81, 0xAD, 0xD2),
  123. imagecolorallocate($im, 0x60, 0x80, 0xDF),
  124. imagecolorallocate($im, 0x00, 0x00, 0xFF)
  125. );
  126. $bmis = array(
  127. 18.5,
  128. 25,
  129. 30,
  130. 35,
  131. 40,
  132. 100
  133. );
  134. fillBMI($im, 0, 18.5, $colours[0], "Underweight");
  135. fillBMI($im, 18.5, 25, $colours[1], "Normal");
  136. fillBMI($im, 25, 30, $colours[2], "Overweight");
  137. fillBMI($im, 30, 35, $colours[3], "Obese class I");
  138. fillBMI($im, 35, 40, $colours[4], "Obese class II");
  139. fillBMI($im, 40, 100, $colours[5], "Obese class III");
  140. for ($i = YMIN; $i < YMAX; $i += 2) {
  141. $y = GHEIGHT - 45 - ($i - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  142. imageline($im, 63, $y, 66, $y, $black);
  143. imagestring($im, 1, 45, $y - 4, STR_PAD($i, 3, ' ', STR_PAD_LEFT), $black);
  144. if ($i % 2 == 0 && $i > YMIN) {
  145. for ($j = 0; $j < count($bmis); $j++) {
  146. if ($bmis[$j] > ($i / (HEIGHT * HEIGHT))) { break; }
  147. }
  148. dashLine($im, $y, $colours[$j+1]);
  149. }
  150. }
  151. for ($i = ceil(YMIN / (HEIGHT*HEIGHT)); $i < ceil(YMAX / (HEIGHT*HEIGHT)); $i++) {
  152. $y = GHEIGHT - 45 - ($i * HEIGHT * HEIGHT - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  153. imageline($im, GWIDTH - 56, $y, GWIDTH - 53, $y, $black);
  154. imagestring($im, 1, GWIDTH - 50, $y - 4, $i, $black);
  155. if ($i % 5 != 0) {
  156. for ($j = 0; $j < count($bmis); $j++) {
  157. if ($bmis[$j] > $i) { break; }
  158. }
  159. dashLine2($im, $y, $colours[$j+1]);
  160. }
  161. }
  162. $lx = $ly = 0;
  163. $points = array();
  164. for($i = 0; $i < XMAX; $i++) {
  165. $x = 65 + ($i - XMIN) * ((GWIDTH - 120) / (XMAX - XMIN));
  166. if ($lx != 0) {
  167. //imageline($im, $lx, $ly, $x, $y, $ly > $y ? $red : $black);
  168. }
  169. imageline($im, $x, GHEIGHT - 46, $x, GHEIGHT - 43, $black);
  170. imagestring($im, 1, $x - 2, GHEIGHT - 40, substr($i + 1, 0, 1), $black);
  171. if ($i >= 9) {
  172. imagestring($im, 1, $x - 2, GHEIGHT - 32, substr($i + 1, 1, 1), $black);
  173. }
  174. #imageline($im, $x - 4, $y - 4, $x + 4, $y + 4, $white);
  175. #imageline($im, $x + 4, $y - 4, $x - 4, $y + 4, $white);
  176. if (isset($data[$i])) {
  177. $weight = $data[$i];
  178. $y = GHEIGHT - 45 - ($weight - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  179. $points[] = array($x, $y);
  180. if ($i % 5 == 4) {
  181. //dashLine3($im, $x, $y, imagecolorallocatealpha($im, 0x66, 0x66, 0x66, 10));// $i % 5 == 4 ? $black : $grey);
  182. //imagearc($im, $x, $y, 10, 10, 0, 360, $red);
  183. }// else {
  184. imagefilledarc($im, $x, $y, 3, 3, 0, 360, $red, IMG_ARC_PIE);
  185. //}
  186. $lx = $x; $ly = $y;
  187. }
  188. }
  189. foreach ($targets as $target) {
  190. list($week, $bmi) = $target;
  191. $weight = $bmi * HEIGHT * HEIGHT;
  192. if ($week > 0) {
  193. $x = 65 + (($week - 1) - XMIN) * ((GWIDTH - 120) / (XMAX - XMIN));
  194. $y = GHEIGHT - 45 - ($weight - YMIN) * ((GHEIGHT - 90) / (YMAX - YMIN));
  195. imageline($im, $x - 4, $y - 4, $x + 4, $y + 4, $red);
  196. imageline($im, $x - 4, $y + 4, $x + 4, $y - 4, $red);
  197. }
  198. }
  199. $avg = array();
  200. $avg[] = $points[0];
  201. for ($i = 0; $i < XMAX - XMIN - 5; $i += 5) {
  202. $tx = $ty = 0;
  203. for ($j = 0; $j < 5; $j++) {
  204. list($x, $y) = $points[$i + $j];
  205. $tx += $x; $ty += $y;
  206. }
  207. $avg[] = array($tx/5, $ty/5);
  208. }
  209. $colours = array($red, $black);
  210. foreach (array(/*$avg,*/ $points) as $points) {
  211. $colour = array_shift($colours);
  212. $lx = $ly = 0;
  213. for ($i = 0; $i < count($points) - 1; $i++) {
  214. $func = interpolate($points, $i, $i + 1);
  215. list($x1,$y1) = $points[$i];
  216. list($x2,$y2) = $points[$i + 1];
  217. for ($t = 0; $t < 1; $t += 4 / ($x2 - $x1)) {
  218. $x = round($x1 + ($x2 - $x1) * $t, 0);
  219. $y = round(call_user_func($func, $t), 0);
  220. if ($lx != 0) {
  221. imagesmoothline($im, $lx, $ly, $x, $y, $red);
  222. }
  223. $lx = $x; $ly = $y;
  224. }
  225. }
  226. }
  227. function h00($t) { return 2 * pow($t, 3) - 3 * pow($t, 2) + 1; }
  228. function h10($t) { return pow($t, 3) - 2 * pow($t, 2) + $t; }
  229. function h01($t) { return -2 * pow($t, 3) + 3 * pow($t, 2); }
  230. function h11($t) { return pow($t, 3) - pow($t, 2); }
  231. function p($t, $p0, $m0, $p1, $m1, $h) { return h00($t) * $p0 + h10($t) * $h * $m0 + h01($t) * $p1 + h11($t) * $h * $m1; }
  232. function getLineGradient($a, $b) {
  233. list($x1,$y1) = $a;
  234. list($x2,$y2) = $b;
  235. $dx = $x2 - $x1;
  236. $dy = $y2 - $y1;
  237. if ($dx == 0) { return PHP_INT_MAX; }
  238. return $dy/$dx;
  239. }
  240. function getPointGradient($cur, $last, $next) {
  241. if ($last == null) { return getLineGradient($cur, $next); }
  242. if ($next == null) { return getLineGradient($last, $cur); }
  243. return (getLineGradient($cur, $next) + getLineGradient($last, $cur))/2;
  244. }
  245. function interpolate($data, $from, $to) {
  246. $prev = isset($data[$from - 1]) ? $data[$from - 1] : null;
  247. $next = isset($data[$to + 1]) ? $data[$to + 1] : null;
  248. $one = $data[$from];
  249. $two = $data[$to];
  250. list($x1, $y1) = $one;
  251. list($x2, $y2) = $two;
  252. $h = $x2 - $x1;
  253. $p0 = $y1; $p1 = $y2;
  254. $m0 = getPointGradient($prev, $one, $two);
  255. $m1 = getPointGradient($one, $two, $next);
  256. return create_function('$t', 'return p($t, ' . $p0 . ', ' . $m0 . ', ' . $p1 . ', ' . $m1 . ', ' . $h . ');');
  257. }
  258. imagestring($im, 3, GWIDTH/2 - 50, GHEIGHT - 20, 'Week number', $black);
  259. imagestringup($im, 3, 10, GHEIGHT/2 + 20, 'Mass (KG)', $black);
  260. imagestringup($im, 3, GWIDTH - 20, GHEIGHT/2 + 50, 'BMI (KG/m^2)', $black);
  261. imagestring($im, 5, GWIDTH/2 - 110, 10, 'Graph of mass against time', $black);
  262. header('Content-type: image/png');
  263. imagepng($im);
  264. ?>