pData.class.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. <?php
  2. /*
  3. pDraw - class to manipulate data arrays
  4. Version : 2.1.4
  5. Made by : Jean-Damien POGOLOTTI
  6. Last Update : 19/01/2014
  7. This file can be distributed under the license you can find at :
  8. http://www.pchart.net/license
  9. You can find the whole class documentation on the pChart web site.
  10. */
  11. /* Axis configuration */
  12. define("AXIS_FORMAT_DEFAULT" , 680001);
  13. define("AXIS_FORMAT_TIME" , 680002);
  14. define("AXIS_FORMAT_DATE" , 680003);
  15. define("AXIS_FORMAT_METRIC" , 680004);
  16. define("AXIS_FORMAT_CURRENCY" , 680005);
  17. define("AXIS_FORMAT_TRAFFIC" , 680006);
  18. define("AXIS_FORMAT_CUSTOM" , 680007);
  19. /* Axis position */
  20. define("AXIS_POSITION_LEFT" , 681001);
  21. define("AXIS_POSITION_RIGHT" , 681002);
  22. define("AXIS_POSITION_TOP" , 681001);
  23. define("AXIS_POSITION_BOTTOM" , 681002);
  24. /* Families of data points */
  25. define("SERIE_SHAPE_FILLEDCIRCLE" , 681011);
  26. define("SERIE_SHAPE_FILLEDTRIANGLE" , 681012);
  27. define("SERIE_SHAPE_FILLEDSQUARE" , 681013);
  28. define("SERIE_SHAPE_FILLEDDIAMOND" , 681017);
  29. define("SERIE_SHAPE_CIRCLE" , 681014);
  30. define("SERIE_SHAPE_TRIANGLE" , 681015);
  31. define("SERIE_SHAPE_SQUARE" , 681016);
  32. define("SERIE_SHAPE_DIAMOND" , 681018);
  33. /* Axis position */
  34. define("AXIS_X" , 682001);
  35. define("AXIS_Y" , 682002);
  36. /* Define value limits */
  37. define("ABSOLUTE_MIN" , -10000000000000);
  38. define("ABSOLUTE_MAX" , 10000000000000);
  39. /* Replacement to the PHP NULL keyword */
  40. define("VOID" , 0.123456789);
  41. /* Euro symbol for GD fonts */
  42. define("EURO_SYMBOL" , utf8_encode("&#8364;"));
  43. /* pData class definition */
  44. class pData
  45. {
  46. var $Data;
  47. var $Palette = array("0"=>array("R"=>188,"G"=>224,"B"=>46,"Alpha"=>100),
  48. "1"=>array("R"=>224,"G"=>100,"B"=>46,"Alpha"=>100),
  49. "2"=>array("R"=>224,"G"=>214,"B"=>46,"Alpha"=>100),
  50. "3"=>array("R"=>46,"G"=>151,"B"=>224,"Alpha"=>100),
  51. "4"=>array("R"=>176,"G"=>46,"B"=>224,"Alpha"=>100),
  52. "5"=>array("R"=>224,"G"=>46,"B"=>117,"Alpha"=>100),
  53. "6"=>array("R"=>92,"G"=>224,"B"=>46,"Alpha"=>100),
  54. "7"=>array("R"=>224,"G"=>176,"B"=>46,"Alpha"=>100));
  55. /* Class creator */
  56. function pData()
  57. {
  58. $this->Data = "";
  59. $this->Data["XAxisDisplay"] = AXIS_FORMAT_DEFAULT;
  60. $this->Data["XAxisFormat"] = NULL;
  61. $this->Data["XAxisName"] = NULL;
  62. $this->Data["XAxisUnit"] = NULL;
  63. $this->Data["Abscissa"] = NULL;
  64. $this->Data["AbsicssaPosition"] = AXIS_POSITION_BOTTOM;
  65. $this->Data["Axis"][0]["Display"] = AXIS_FORMAT_DEFAULT;
  66. $this->Data["Axis"][0]["Position"] = AXIS_POSITION_LEFT;
  67. $this->Data["Axis"][0]["Identity"] = AXIS_Y;
  68. }
  69. /* Add a single point or an array to the given serie */
  70. function addPoints($Values,$SerieName="Serie1")
  71. {
  72. if (!isset($this->Data["Series"][$SerieName]))
  73. $this->initialise($SerieName);
  74. if ( is_array($Values) )
  75. {
  76. foreach($Values as $Key => $Value)
  77. { $this->Data["Series"][$SerieName]["Data"][] = $Value; }
  78. }
  79. else
  80. $this->Data["Series"][$SerieName]["Data"][] = $Values;
  81. if ( $Values != VOID )
  82. {
  83. $StrippedData = $this->stripVOID($this->Data["Series"][$SerieName]["Data"]);
  84. if ( empty($StrippedData) ) { $this->Data["Series"][$SerieName]["Max"] = 0; $this->Data["Series"][$SerieName]["Min"] =0; return(0); }
  85. $this->Data["Series"][$SerieName]["Max"] = max($StrippedData);
  86. $this->Data["Series"][$SerieName]["Min"] = min($StrippedData);
  87. }
  88. }
  89. /* Strip VOID values */
  90. function stripVOID($Values)
  91. { if (!is_array($Values)) { return(array()); } $Result = array(); foreach($Values as $Key => $Value) { if ( $Value != VOID ) { $Result[] = $Value; } } return($Result); }
  92. /* Return the number of values contained in a given serie */
  93. function getSerieCount($Serie)
  94. { if (isset($this->Data["Series"][$Serie]["Data"])) { return(sizeof($this->Data["Series"][$Serie]["Data"])); } else { return(0); } }
  95. /* Remove a serie from the pData object */
  96. function removeSerie($Series)
  97. {
  98. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  99. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie])) { unset($this->Data["Series"][$Serie]); } }
  100. }
  101. /* Return a value from given serie & index */
  102. function getValueAt($Serie,$Index=0)
  103. { if (isset($this->Data["Series"][$Serie]["Data"][$Index])) { return($this->Data["Series"][$Serie]["Data"][$Index]); } else { return(NULL); } }
  104. /* Return the values array */
  105. function getValues($Serie)
  106. { if (isset($this->Data["Series"][$Serie]["Data"])) { return($this->Data["Series"][$Serie]["Data"]); } else { return(NULL); } }
  107. /* Reverse the values in the given serie */
  108. function reverseSerie($Series)
  109. {
  110. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  111. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]["Data"])) { $this->Data["Series"][$Serie]["Data"] = array_reverse($this->Data["Series"][$Serie]["Data"]); } }
  112. }
  113. /* Return the sum of the serie values */
  114. function getSum($Serie)
  115. { if (isset($this->Data["Series"][$Serie])) { return(array_sum($this->Data["Series"][$Serie]["Data"])); } else { return(NULL); } }
  116. /* Return the max value of a given serie */
  117. function getMax($Serie)
  118. { if (isset($this->Data["Series"][$Serie]["Max"])) { return($this->Data["Series"][$Serie]["Max"]); } else { return(NULL); } }
  119. /* Return the min value of a given serie */
  120. function getMin($Serie)
  121. { if (isset($this->Data["Series"][$Serie]["Min"])) { return($this->Data["Series"][$Serie]["Min"]); } else { return(NULL); } }
  122. /* Set the description of a given serie */
  123. function setSerieShape($Series,$Shape=SERIE_SHAPE_FILLEDCIRCLE)
  124. {
  125. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  126. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Shape"] = $Shape; } }
  127. }
  128. /* Set the description of a given serie */
  129. function setSerieDescription($Series,$Description="My serie")
  130. {
  131. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  132. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Description"] = $Description; } }
  133. }
  134. /* Set a serie as "drawable" while calling a rendering function */
  135. function setSerieDrawable($Series,$Drawable=TRUE)
  136. {
  137. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  138. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["isDrawable"] = $Drawable; } }
  139. }
  140. /* Set the icon associated to a given serie */
  141. function setSeriePicture($Series,$Picture=NULL)
  142. {
  143. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  144. foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Picture"] = $Picture; } }
  145. }
  146. /* Set the name of the X Axis */
  147. function setXAxisName($Name)
  148. { $this->Data["XAxisName"] = $Name; }
  149. /* Set the display mode of the X Axis */
  150. function setXAxisDisplay($Mode,$Format=NULL)
  151. { $this->Data["XAxisDisplay"] = $Mode; $this->Data["XAxisFormat"] = $Format; }
  152. /* Set the unit that will be displayed on the X axis */
  153. function setXAxisUnit($Unit)
  154. { $this->Data["XAxisUnit"] = $Unit; }
  155. /* Set the serie that will be used as abscissa */
  156. function setAbscissa($Serie)
  157. { if (isset($this->Data["Series"][$Serie])) { $this->Data["Abscissa"] = $Serie; } }
  158. function setAbsicssaPosition($Position = AXIS_POSITION_BOTTOM)
  159. { $this->Data["AbsicssaPosition"] = $Position; }
  160. /* Set the name of the abscissa axis */
  161. function setAbscissaName($Name)
  162. { $this->Data["AbscissaName"] = $Name; }
  163. /* Create a scatter group specifyin X and Y data series */
  164. function setScatterSerie($SerieX,$SerieY,$ID=0)
  165. { if (isset($this->Data["Series"][$SerieX]) && isset($this->Data["Series"][$SerieY]) ) { $this->initScatterSerie($ID); $this->Data["ScatterSeries"][$ID]["X"] = $SerieX; $this->Data["ScatterSeries"][$ID]["Y"] = $SerieY; } }
  166. /* Set the shape of a given sctatter serie */
  167. function setScatterSerieShape($ID,$Shape=SERIE_SHAPE_FILLEDCIRCLE)
  168. { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Shape"] = $Shape; } }
  169. /* Set the description of a given scatter serie */
  170. function setScatterSerieDescription($ID,$Description="My serie")
  171. { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Description"] = $Description; } }
  172. /* Set the icon associated to a given scatter serie */
  173. function setScatterSeriePicture($ID,$Picture=NULL)
  174. { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Picture"] = $Picture; } }
  175. /* Set a scatter serie as "drawable" while calling a rendering function */
  176. function setScatterSerieDrawable($ID ,$Drawable=TRUE)
  177. { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["isDrawable"] = $Drawable; } }
  178. /* Define if a scatter serie should be draw with ticks */
  179. function setScatterSerieTicks($ID,$Width=0)
  180. { if ( isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Ticks"] = $Width; } }
  181. /* Define if a scatter serie should be draw with a special weight */
  182. function setScatterSerieWeight($ID,$Weight=0)
  183. { if ( isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Weight"] = $Weight; } }
  184. /* Associate a color to a scatter serie */
  185. function setScatterSerieColor($ID,$Format)
  186. {
  187. $R = isset($Format["R"]) ? $Format["R"] : 0;
  188. $G = isset($Format["G"]) ? $Format["G"] : 0;
  189. $B = isset($Format["B"]) ? $Format["B"] : 0;
  190. $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  191. if ( isset($this->Data["ScatterSeries"][$ID]) )
  192. {
  193. $this->Data["ScatterSeries"][$ID]["Color"]["R"] = $R;
  194. $this->Data["ScatterSeries"][$ID]["Color"]["G"] = $G;
  195. $this->Data["ScatterSeries"][$ID]["Color"]["B"] = $B;
  196. $this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = $Alpha;
  197. }
  198. }
  199. /* Compute the series limits for an individual and global point of view */
  200. function limits()
  201. {
  202. $GlobalMin = ABSOLUTE_MAX;
  203. $GlobalMax = ABSOLUTE_MIN;
  204. foreach($this->Data["Series"] as $Key => $Value)
  205. {
  206. if ( $this->Data["Abscissa"] != $Key && $this->Data["Series"][$Key]["isDrawable"] == TRUE)
  207. {
  208. if ( $GlobalMin > $this->Data["Series"][$Key]["Min"] ) { $GlobalMin = $this->Data["Series"][$Key]["Min"]; }
  209. if ( $GlobalMax < $this->Data["Series"][$Key]["Max"] ) { $GlobalMax = $this->Data["Series"][$Key]["Max"]; }
  210. }
  211. }
  212. $this->Data["Min"] = $GlobalMin;
  213. $this->Data["Max"] = $GlobalMax;
  214. return(array($GlobalMin,$GlobalMax));
  215. }
  216. /* Mark all series as drawable */
  217. function drawAll()
  218. { foreach($this->Data["Series"] as $Key => $Value) { if ( $this->Data["Abscissa"] != $Key ) { $this->Data["Series"][$Key]["isDrawable"]=TRUE; } } }
  219. /* Return the average value of the given serie */
  220. function getSerieAverage($Serie)
  221. {
  222. if ( isset($this->Data["Series"][$Serie]) )
  223. {
  224. $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
  225. return(array_sum($SerieData)/sizeof($SerieData));
  226. }
  227. else
  228. return(NULL);
  229. }
  230. /* Return the geometric mean of the given serie */
  231. function getGeometricMean($Serie)
  232. {
  233. if ( isset($this->Data["Series"][$Serie]) )
  234. {
  235. $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
  236. $Seriesum = 1; foreach($SerieData as $Key => $Value) { $Seriesum = $Seriesum * $Value; }
  237. return(pow($Seriesum,1/sizeof($SerieData)));
  238. }
  239. else
  240. return(NULL);
  241. }
  242. /* Return the harmonic mean of the given serie */
  243. function getHarmonicMean($Serie)
  244. {
  245. if ( isset($this->Data["Series"][$Serie]) )
  246. {
  247. $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
  248. $Seriesum = 0; foreach($SerieData as $Key => $Value) { $Seriesum = $Seriesum + 1/$Value; }
  249. return(sizeof($SerieData)/$Seriesum);
  250. }
  251. else
  252. return(NULL);
  253. }
  254. /* Return the standard deviation of the given serie */
  255. function getStandardDeviation($Serie)
  256. {
  257. if ( isset($this->Data["Series"][$Serie]) )
  258. {
  259. $Average = $this->getSerieAverage($Serie);
  260. $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
  261. $DeviationSum = 0;
  262. foreach($SerieData as $Key => $Value)
  263. $DeviationSum = $DeviationSum + ($Value-$Average)*($Value-$Average);
  264. $Deviation = sqrt($DeviationSum/count($SerieData));
  265. return($Deviation);
  266. }
  267. else
  268. return(NULL);
  269. }
  270. /* Return the Coefficient of variation of the given serie */
  271. function getCoefficientOfVariation($Serie)
  272. {
  273. if ( isset($this->Data["Series"][$Serie]) )
  274. {
  275. $Average = $this->getSerieAverage($Serie);
  276. $StandardDeviation = $this->getStandardDeviation($Serie);
  277. if ( $StandardDeviation != 0 )
  278. return($StandardDeviation/$Average);
  279. else
  280. return(NULL);
  281. }
  282. else
  283. return(NULL);
  284. }
  285. /* Return the median value of the given serie */
  286. function getSerieMedian($Serie)
  287. {
  288. if ( isset($this->Data["Series"][$Serie]) )
  289. {
  290. $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
  291. sort($SerieData);
  292. $SerieCenter = floor(sizeof($SerieData)/2);
  293. if ( isset($SerieData[$SerieCenter]) )
  294. return($SerieData[$SerieCenter]);
  295. else
  296. return(NULL);
  297. }
  298. else
  299. return(NULL);
  300. }
  301. /* Return the x th percentil of the given serie */
  302. function getSeriePercentile($Serie="Serie1",$Percentil=95)
  303. {
  304. if (!isset($this->Data["Series"][$Serie]["Data"])) { return(NULL); }
  305. $Values = count($this->Data["Series"][$Serie]["Data"])-1;
  306. if ( $Values < 0 ) { $Values = 0; }
  307. $PercentilID = floor(($Values/100)*$Percentil+.5);
  308. $SortedValues = $this->Data["Series"][$Serie]["Data"];
  309. sort($SortedValues);
  310. if ( is_numeric($SortedValues[$PercentilID]) )
  311. return($SortedValues[$PercentilID]);
  312. else
  313. return(NULL);
  314. }
  315. /* Add random values to a given serie */
  316. function addRandomValues($SerieName="Serie1",$Options="")
  317. {
  318. $Values = isset($Options["Values"]) ? $Options["Values"] : 20;
  319. $Min = isset($Options["Min"]) ? $Options["Min"] : 0;
  320. $Max = isset($Options["Max"]) ? $Options["Max"] : 100;
  321. $withFloat = isset($Options["withFloat"]) ? $Options["withFloat"] : FALSE;
  322. for ($i=0;$i<=$Values;$i++)
  323. {
  324. if ( $withFloat ) { $Value = rand($Min*100,$Max*100)/100; } else { $Value = rand($Min,$Max); }
  325. $this->addPoints($Value,$SerieName);
  326. }
  327. }
  328. /* Test if we have valid data */
  329. function containsData()
  330. {
  331. if (!isset($this->Data["Series"])) { return(FALSE); }
  332. $Result = FALSE;
  333. foreach($this->Data["Series"] as $Key => $Value)
  334. { if ( $this->Data["Abscissa"] != $Key && $this->Data["Series"][$Key]["isDrawable"]==TRUE) { $Result=TRUE; } }
  335. return($Result);
  336. }
  337. /* Set the display mode of an Axis */
  338. function setAxisDisplay($AxisID,$Mode=AXIS_FORMAT_DEFAULT,$Format=NULL)
  339. {
  340. if ( isset($this->Data["Axis"][$AxisID] ) )
  341. {
  342. $this->Data["Axis"][$AxisID]["Display"] = $Mode;
  343. if ( $Format != NULL ) { $this->Data["Axis"][$AxisID]["Format"] = $Format; }
  344. }
  345. }
  346. /* Set the position of an Axis */
  347. function setAxisPosition($AxisID,$Position=AXIS_POSITION_LEFT)
  348. { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Position"] = $Position; } }
  349. /* Associate an unit to an axis */
  350. function setAxisUnit($AxisID,$Unit)
  351. { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Unit"] = $Unit; } }
  352. /* Associate a name to an axis */
  353. function setAxisName($AxisID,$Name)
  354. { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Name"] = $Name; } }
  355. /* Associate a color to an axis */
  356. function setAxisColor($AxisID,$Format)
  357. {
  358. $R = isset($Format["R"]) ? $Format["R"] : 0;
  359. $G = isset($Format["G"]) ? $Format["G"] : 0;
  360. $B = isset($Format["B"]) ? $Format["B"] : 0;
  361. $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  362. if ( isset($this->Data["Axis"][$AxisID] ) )
  363. {
  364. $this->Data["Axis"][$AxisID]["Color"]["R"] = $R;
  365. $this->Data["Axis"][$AxisID]["Color"]["G"] = $G;
  366. $this->Data["Axis"][$AxisID]["Color"]["B"] = $B;
  367. $this->Data["Axis"][$AxisID]["Color"]["Alpha"] = $Alpha;
  368. }
  369. }
  370. /* Design an axis as X or Y member */
  371. function setAxisXY($AxisID,$Identity=AXIS_Y)
  372. { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Identity"] = $Identity; } }
  373. /* Associate one data serie with one axis */
  374. function setSerieOnAxis($Series,$AxisID)
  375. {
  376. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  377. foreach($Series as $Key => $Serie)
  378. {
  379. $PreviousAxis = $this->Data["Series"][$Serie]["Axis"];
  380. /* Create missing axis */
  381. if ( !isset($this->Data["Axis"][$AxisID] ) )
  382. { $this->Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT; $this->Data["Axis"][$AxisID]["Identity"] = AXIS_Y;}
  383. $this->Data["Series"][$Serie]["Axis"] = $AxisID;
  384. /* Cleanup unused axis */
  385. $Found = FALSE;
  386. foreach($this->Data["Series"] as $SerieName => $Values) { if ( $Values["Axis"] == $PreviousAxis ) { $Found = TRUE; } }
  387. if (!$Found) { unset($this->Data["Axis"][$PreviousAxis]); }
  388. }
  389. }
  390. /* Define if a serie should be draw with ticks */
  391. function setSerieTicks($Series,$Width=0)
  392. {
  393. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  394. foreach($Series as $Key => $Serie) { if ( isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Ticks"] = $Width; } }
  395. }
  396. /* Define if a serie should be draw with a special weight */
  397. function setSerieWeight($Series,$Weight=0)
  398. {
  399. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  400. foreach($Series as $Key => $Serie) { if ( isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Weight"] = $Weight; } }
  401. }
  402. /* Returns the palette of the given serie */
  403. function getSeriePalette($Serie)
  404. {
  405. if ( !isset($this->Data["Series"][$Serie]) ) { return(NULL); }
  406. $Result = "";
  407. $Result["R"] = $this->Data["Series"][$Serie]["Color"]["R"];
  408. $Result["G"] = $this->Data["Series"][$Serie]["Color"]["G"];
  409. $Result["B"] = $this->Data["Series"][$Serie]["Color"]["B"];
  410. $Result["Alpha"] = $this->Data["Series"][$Serie]["Color"]["Alpha"];
  411. return($Result);
  412. }
  413. /* Set the color of one serie */
  414. function setPalette($Series,$Format=NULL)
  415. {
  416. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  417. foreach($Series as $Key => $Serie)
  418. {
  419. $R = isset($Format["R"]) ? $Format["R"] : 0;
  420. $G = isset($Format["G"]) ? $Format["G"] : 0;
  421. $B = isset($Format["B"]) ? $Format["B"] : 0;
  422. $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
  423. if ( isset($this->Data["Series"][$Serie]) )
  424. {
  425. $OldR = $this->Data["Series"][$Serie]["Color"]["R"]; $OldG = $this->Data["Series"][$Serie]["Color"]["G"]; $OldB = $this->Data["Series"][$Serie]["Color"]["B"];
  426. $this->Data["Series"][$Serie]["Color"]["R"] = $R;
  427. $this->Data["Series"][$Serie]["Color"]["G"] = $G;
  428. $this->Data["Series"][$Serie]["Color"]["B"] = $B;
  429. $this->Data["Series"][$Serie]["Color"]["Alpha"] = $Alpha;
  430. /* Do reverse processing on the internal palette array */
  431. foreach ($this->Palette as $Key => $Value)
  432. { if ($Value["R"] == $OldR && $Value["G"] == $OldG && $Value["B"] == $OldB) { $this->Palette[$Key]["R"] = $R; $this->Palette[$Key]["G"] = $G; $this->Palette[$Key]["B"] = $B; $this->Palette[$Key]["Alpha"] = $Alpha;} }
  433. }
  434. }
  435. }
  436. /* Load a palette file */
  437. function loadPalette($FileName,$Overwrite=FALSE)
  438. {
  439. if ( !file_exists($FileName) ) { return(-1); }
  440. if ( $Overwrite ) { $this->Palette = ""; }
  441. $fileHandle = @fopen($FileName, "r");
  442. if (!$fileHandle) { return(-1); }
  443. while (!feof($fileHandle))
  444. {
  445. $buffer = fgets($fileHandle, 4096);
  446. if ( preg_match("/,/",$buffer) )
  447. {
  448. list($R,$G,$B,$Alpha) = preg_split("/,/",$buffer);
  449. if ( $this->Palette == "" ) { $ID = 0; } else { $ID = count($this->Palette); }
  450. $this->Palette[$ID] = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
  451. }
  452. }
  453. fclose($fileHandle);
  454. /* Apply changes to current series */
  455. $ID = 0;
  456. if ( isset($this->Data["Series"]))
  457. {
  458. foreach($this->Data["Series"] as $Key => $Value)
  459. {
  460. if ( !isset($this->Palette[$ID]) )
  461. $this->Data["Series"][$Key]["Color"] = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>0);
  462. else
  463. $this->Data["Series"][$Key]["Color"] = $this->Palette[$ID];
  464. $ID++;
  465. }
  466. }
  467. }
  468. /* Initialise a given scatter serie */
  469. function initScatterSerie($ID)
  470. {
  471. if ( isset($this->Data["ScatterSeries"][$ID]) ) { return(0); }
  472. $this->Data["ScatterSeries"][$ID]["Description"] = "Scatter ".$ID;
  473. $this->Data["ScatterSeries"][$ID]["isDrawable"] = TRUE;
  474. $this->Data["ScatterSeries"][$ID]["Picture"] = NULL;
  475. $this->Data["ScatterSeries"][$ID]["Ticks"] = 0;
  476. $this->Data["ScatterSeries"][$ID]["Weight"] = 0;
  477. if ( isset($this->Palette[$ID]) )
  478. $this->Data["ScatterSeries"][$ID]["Color"] = $this->Palette[$ID];
  479. else
  480. {
  481. $this->Data["ScatterSeries"][$ID]["Color"]["R"] = rand(0,255);
  482. $this->Data["ScatterSeries"][$ID]["Color"]["G"] = rand(0,255);
  483. $this->Data["ScatterSeries"][$ID]["Color"]["B"] = rand(0,255);
  484. $this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = 100;
  485. }
  486. }
  487. /* Initialise a given serie */
  488. function initialise($Serie)
  489. {
  490. if ( isset($this->Data["Series"]) ) { $ID = count($this->Data["Series"]); } else { $ID = 0; }
  491. $this->Data["Series"][$Serie]["Description"] = $Serie;
  492. $this->Data["Series"][$Serie]["isDrawable"] = TRUE;
  493. $this->Data["Series"][$Serie]["Picture"] = NULL;
  494. $this->Data["Series"][$Serie]["Max"] = NULL;
  495. $this->Data["Series"][$Serie]["Min"] = NULL;
  496. $this->Data["Series"][$Serie]["Axis"] = 0;
  497. $this->Data["Series"][$Serie]["Ticks"] = 0;
  498. $this->Data["Series"][$Serie]["Weight"] = 0;
  499. $this->Data["Series"][$Serie]["Shape"] = SERIE_SHAPE_FILLEDCIRCLE;
  500. if ( isset($this->Palette[$ID]) )
  501. $this->Data["Series"][$Serie]["Color"] = $this->Palette[$ID];
  502. else
  503. {
  504. $this->Data["Series"][$Serie]["Color"]["R"] = rand(0,255);
  505. $this->Data["Series"][$Serie]["Color"]["G"] = rand(0,255);
  506. $this->Data["Series"][$Serie]["Color"]["B"] = rand(0,255);
  507. $this->Data["Series"][$Serie]["Color"]["Alpha"] = 100;
  508. }
  509. }
  510. function normalize($NormalizationFactor=100,$UnitChange=NULL,$Round=1)
  511. {
  512. $Abscissa = $this->Data["Abscissa"];
  513. $SelectedSeries = "";
  514. $MaxVal = 0;
  515. foreach($this->Data["Axis"] as $AxisID => $Axis)
  516. {
  517. if ( $UnitChange != NULL ) { $this->Data["Axis"][$AxisID]["Unit"] = $UnitChange; }
  518. foreach($this->Data["Series"] as $SerieName => $Serie)
  519. {
  520. if ($Serie["Axis"] == $AxisID && $Serie["isDrawable"] == TRUE && $SerieName != $Abscissa)
  521. {
  522. $SelectedSeries[$SerieName] = $SerieName;
  523. if ( count($Serie["Data"] ) > $MaxVal ) { $MaxVal = count($Serie["Data"]); }
  524. }
  525. }
  526. }
  527. for($i=0;$i<=$MaxVal-1;$i++)
  528. {
  529. $Factor = 0;
  530. foreach ($SelectedSeries as $Key => $SerieName )
  531. {
  532. $Value = $this->Data["Series"][$SerieName]["Data"][$i];
  533. if ( $Value != VOID )
  534. $Factor = $Factor + abs($Value);
  535. }
  536. if ( $Factor != 0 )
  537. {
  538. $Factor = $NormalizationFactor / $Factor;
  539. foreach ($SelectedSeries as $Key => $SerieName )
  540. {
  541. $Value = $this->Data["Series"][$SerieName]["Data"][$i];
  542. if ( $Value != VOID && $Factor != $NormalizationFactor )
  543. $this->Data["Series"][$SerieName]["Data"][$i] = round(abs($Value)*$Factor,$Round);
  544. elseif ( $Value == VOID || $Value == 0 )
  545. $this->Data["Series"][$SerieName]["Data"][$i] = VOID;
  546. elseif ( $Factor == $NormalizationFactor )
  547. $this->Data["Series"][$SerieName]["Data"][$i] = $NormalizationFactor;
  548. }
  549. }
  550. }
  551. foreach ($SelectedSeries as $Key => $SerieName )
  552. {
  553. $this->Data["Series"][$SerieName]["Max"] = max($this->stripVOID($this->Data["Series"][$SerieName]["Data"]));
  554. $this->Data["Series"][$SerieName]["Min"] = min($this->stripVOID($this->Data["Series"][$SerieName]["Data"]));
  555. }
  556. }
  557. /* Load data from a CSV (or similar) data source */
  558. function importFromCSV($FileName,$Options="")
  559. {
  560. $Delimiter = isset($Options["Delimiter"]) ? $Options["Delimiter"] : ",";
  561. $GotHeader = isset($Options["GotHeader"]) ? $Options["GotHeader"] : FALSE;
  562. $SkipColumns = isset($Options["SkipColumns"]) ? $Options["SkipColumns"] : array(-1);
  563. $DefaultSerieName = isset($Options["DefaultSerieName"]) ? $Options["DefaultSerieName"] : "Serie";
  564. $Handle = @fopen($FileName,"r");
  565. if ($Handle)
  566. {
  567. $HeaderParsed = FALSE; $SerieNames = "";
  568. while (!feof($Handle))
  569. {
  570. $Buffer = fgets($Handle, 4096);
  571. $Buffer = str_replace(chr(10),"",$Buffer);
  572. $Buffer = str_replace(chr(13),"",$Buffer);
  573. $Values = preg_split("/".$Delimiter."/",$Buffer);
  574. if ( $Buffer != "" )
  575. {
  576. if ( $GotHeader && !$HeaderParsed )
  577. {
  578. foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $Name; } }
  579. $HeaderParsed = TRUE;
  580. }
  581. else
  582. {
  583. if ($SerieNames == "" ) { foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $DefaultSerieName.$Key; } } }
  584. foreach($Values as $Key => $Value) { if ( !in_array($Key,$SkipColumns) ) { $this->addPoints($Value,$SerieNames[$Key]); } }
  585. }
  586. }
  587. }
  588. fclose($Handle);
  589. }
  590. }
  591. /* Create a dataset based on a formula */
  592. function createFunctionSerie($SerieName,$Formula="",$Options="")
  593. {
  594. $MinX = isset($Options["MinX"]) ? $Options["MinX"] : -10;
  595. $MaxX = isset($Options["MaxX"]) ? $Options["MaxX"] : 10;
  596. $XStep = isset($Options["XStep"]) ? $Options["XStep"] : 1;
  597. $AutoDescription = isset($Options["AutoDescription"]) ? $Options["AutoDescription"] : FALSE;
  598. $RecordAbscissa = isset($Options["RecordAbscissa"]) ? $Options["RecordAbscissa"] : FALSE;
  599. $AbscissaSerie = isset($Options["AbscissaSerie"]) ? $Options["AbscissaSerie"] : "Abscissa";
  600. if ( $Formula == "" ) { return(0); }
  601. $Result = ""; $Abscissa = "";
  602. for($i=$MinX; $i<=$MaxX; $i=$i+$XStep)
  603. {
  604. $Expression = "\$return = '!'.(".str_replace("z",$i,$Formula).");";
  605. if ( @eval($Expression) === FALSE ) { $return = VOID; }
  606. if ( $return == "!" ) { $return = VOID; } else { $return = $this->right($return,strlen($return)-1); }
  607. if ( $return == "NAN" ) { $return = VOID; }
  608. if ( $return == "INF" ) { $return = VOID; }
  609. if ( $return == "-INF" ) { $return = VOID; }
  610. $Abscissa[] = $i;
  611. $Result[] = $return;
  612. }
  613. $this->addPoints($Result,$SerieName);
  614. if ( $AutoDescription ) { $this->setSerieDescription($SerieName,$Formula); }
  615. if ( $RecordAbscissa ) { $this->addPoints($Abscissa,$AbscissaSerie); }
  616. }
  617. function negateValues($Series)
  618. {
  619. if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); }
  620. foreach($Series as $Key => $SerieName)
  621. {
  622. if (isset($this->Data["Series"][$SerieName]))
  623. {
  624. $Data = "";
  625. foreach($this->Data["Series"][$SerieName]["Data"] as $Key => $Value)
  626. { if ( $Value == VOID ) { $Data[] = VOID; } else { $Data[] = -$Value; } }
  627. $this->Data["Series"][$SerieName]["Data"] = $Data;
  628. $this->Data["Series"][$SerieName]["Max"] = max($this->stripVOID($this->Data["Series"][$SerieName]["Data"]));
  629. $this->Data["Series"][$SerieName]["Min"] = min($this->stripVOID($this->Data["Series"][$SerieName]["Data"]));
  630. }
  631. }
  632. }
  633. /* Return the data & configuration of the series */
  634. function getData()
  635. { return($this->Data); }
  636. /* Save a palette element */
  637. function savePalette($ID,$Color)
  638. { $this->Palette[$ID] = $Color; }
  639. /* Return the palette of the series */
  640. function getPalette()
  641. { return($this->Palette); }
  642. /* Called by the scaling algorithm to save the config */
  643. function saveAxisConfig($Axis) { $this->Data["Axis"]=$Axis; }
  644. /* Save the Y Margin if set */
  645. function saveYMargin($Value) { $this->Data["YMargin"]=$Value; }
  646. /* Save extended configuration to the pData object */
  647. function saveExtendedData($Tag,$Values) { $this->Data["Extended"][$Tag]=$Values; }
  648. /* Called by the scaling algorithm to save the orientation of the scale */
  649. function saveOrientation($Orientation) { $this->Data["Orientation"]=$Orientation; }
  650. /* Convert a string to a single elements array */
  651. function convertToArray($Value)
  652. { $Values = ""; $Values[] = $Value; return($Values); }
  653. /* Class string wrapper */
  654. function __toString()
  655. { return("pData object."); }
  656. function left($value,$NbChar) { return substr($value,0,$NbChar); }
  657. function right($value,$NbChar) { return substr($value,strlen($value)-$NbChar,$NbChar); }
  658. function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); }
  659. }
  660. ?>