PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/zeta/Graph/src/axis/logarithmic.php

https://gitlab.com/OnBlox/OnBlox-Template
PHP | 357 lines | 174 code | 24 blank | 159 comment | 20 complexity | b63585ffd30e4702cb265fb6dd1e25a5 MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcGraphChartElementLogarithmicalAxis class
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package Graph
  23. * @version //autogentag//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. */
  26. /**
  27. * Class to represent a logarithmic axis.
  28. *
  29. * Axis elements represent the axis in a bar, line or radar chart. They are
  30. * chart elements (ezcGraphChartElement) extending from
  31. * ezcGraphChartElementAxis, where additional formatting options can be found.
  32. * You should generally use the axis, which matches your input data best, so
  33. * that the automatic chart layouting works best. Aavailable axis types are:
  34. *
  35. * - ezcGraphChartElementDateAxis
  36. * - ezcGraphChartElementLabeledAxis
  37. * - ezcGraphChartElementLogarithmicalAxis
  38. * - ezcGraphChartElementNumericAxis
  39. *
  40. * Logarithmic axis are normally used to display very large or small values.
  41. * Logarithmic axis can not be used for value spans including zero, so you
  42. * should either pass only positive or only negative values to the chart.
  43. *
  44. * By default the axis uses a base of 10 for scaling, you may assign any other
  45. * base to the $base property of the chart. With a base of 10 the steps on the
  46. * axis may, for example, be at: 1, 10, 100, 1000, 10000, ...
  47. *
  48. * The logarithmic axis may be used like:
  49. *
  50. * <code>
  51. * $graph = new ezcGraphLineChart();
  52. * $graph->title = 'The power of x';
  53. * $graph->legend->position = ezcGraph::BOTTOM;
  54. *
  55. * $graph->xAxis = new ezcGraphChartElementNumericAxis();
  56. * $graph->yAxis = new ezcGraphChartElementLogarithmicalAxis();
  57. *
  58. * $graph->data['x^2'] = new ezcGraphNumericDataSet(
  59. * -10, 10,
  60. * create_function( '$x', 'return pow( $x, 2 ) + 1;' )
  61. * );
  62. *
  63. * $graph->data['x^4'] = new ezcGraphNumericDataSet(
  64. * -10, 10,
  65. * create_function( '$x', 'return pow( $x, 4 ) + 1;' )
  66. * );
  67. *
  68. * $graph->data['x^6'] = new ezcGraphNumericDataSet(
  69. * -10, 10,
  70. * create_function( '$x', 'return pow( $x, 6 ) + 1;' )
  71. * );
  72. *
  73. * $graph->render( 400, 250, 'tutorial_axis_logarithmic.svg' );
  74. * </code>
  75. *
  76. * @property float $base
  77. * Base for logarithmical scaling.
  78. * @property string $logarithmicalFormatString
  79. * Sprintf formatstring for the axis labels where
  80. * $1 is the base and
  81. * $2 is the exponent.
  82. * @property-read float $minValue
  83. * Minimum Value to display on this axis.
  84. * @property-read float $maxValue
  85. * Maximum value to display on this axis.
  86. *
  87. * @version //autogentag//
  88. * @package Graph
  89. * @mainclass
  90. */
  91. class ezcGraphChartElementLogarithmicalAxis extends ezcGraphChartElementAxis
  92. {
  93. /**
  94. * Constant used for calculation of automatic definition of major scaling
  95. * steps
  96. */
  97. const MAX_STEPS = 9;
  98. /**
  99. * Constructor
  100. *
  101. * @param array $options Default option array
  102. * @return void
  103. * @ignore
  104. */
  105. public function __construct( array $options = array() )
  106. {
  107. $this->properties['min'] = null;
  108. $this->properties['max'] = null;
  109. $this->properties['base'] = 10;
  110. $this->properties['logarithmicalFormatString'] = '%1$d^%2$d';
  111. $this->properties['minValue'] = null;
  112. $this->properties['maxValue'] = null;
  113. parent::__construct( $options );
  114. }
  115. /**
  116. * __set
  117. *
  118. * @param mixed $propertyName
  119. * @param mixed $propertyValue
  120. * @throws ezcBaseValueException
  121. * If a submitted parameter was out of range or type.
  122. * @throws ezcBasePropertyNotFoundException
  123. * If a the value for the property options is not an instance of
  124. * @return void
  125. * @ignore
  126. */
  127. public function __set( $propertyName, $propertyValue )
  128. {
  129. switch ( $propertyName )
  130. {
  131. case 'min':
  132. case 'max':
  133. if ( !is_numeric( $propertyValue ) )
  134. {
  135. throw new ezcBaseValueException( $propertyName, $propertyValue, 'float' );
  136. }
  137. $this->properties[$propertyName] = (float) $propertyValue;
  138. $this->properties['initialized'] = true;
  139. break;
  140. case 'base':
  141. if ( !is_numeric( $propertyValue ) ||
  142. ( $propertyValue <= 0 ) )
  143. {
  144. throw new ezcBaseValueException( $propertyName, $propertyValue, 'float > 0' );
  145. }
  146. $this->properties[$propertyName] = (float) $propertyValue;
  147. break;
  148. case 'logarithmicalFormatString':
  149. $this->properties['logarithmicalFormatString'] = (string) $propertyValue;
  150. break;
  151. default:
  152. parent::__set( $propertyName, $propertyValue );
  153. break;
  154. }
  155. }
  156. /**
  157. * Add data for this axis
  158. *
  159. * @param array $values Value which will be displayed on this axis
  160. * @return void
  161. */
  162. public function addData( array $values )
  163. {
  164. foreach ( $values as $value )
  165. {
  166. if ( $this->properties['minValue'] === null ||
  167. $value < $this->properties['minValue'] )
  168. {
  169. $this->properties['minValue'] = $value;
  170. }
  171. if ( $this->properties['maxValue'] === null ||
  172. $value > $this->properties['maxValue'] )
  173. {
  174. $this->properties['maxValue'] = $value;
  175. }
  176. }
  177. $this->properties['initialized'] = true;
  178. }
  179. /**
  180. * Calculate axis bounding values on base of the assigned values
  181. *
  182. * @abstract
  183. * @access public
  184. * @return void
  185. */
  186. public function calculateAxisBoundings()
  187. {
  188. // Prevent division by zero, when min == max
  189. if ( $this->properties['minValue'] == $this->properties['maxValue'] )
  190. {
  191. if ( $this->properties['minValue'] == 0 )
  192. {
  193. $this->properties['maxValue'] = 1;
  194. }
  195. else
  196. {
  197. $this->properties['minValue'] -= ( $this->properties['minValue'] * .1 );
  198. $this->properties['maxValue'] += ( $this->properties['maxValue'] * .1 );
  199. }
  200. }
  201. if ( $this->properties['minValue'] <= 0 )
  202. {
  203. throw new ezcGraphOutOfLogithmicalBoundingsException( $this->properties['minValue'] );
  204. }
  205. // Use custom minimum and maximum if available
  206. if ( $this->properties['min'] !== null )
  207. {
  208. $this->properties['minValue'] = pow( $this->properties['base'], $this->properties['min'] );
  209. }
  210. if ( $this->properties['max'] !== null )
  211. {
  212. $this->properties['maxValue'] = pow( $this->properties['base'], $this->properties['max'] );
  213. }
  214. // Calculate "nice" values for scaling parameters
  215. if ( $this->properties['min'] === null )
  216. {
  217. $this->properties['min'] = floor( log( $this->properties['minValue'], $this->properties['base'] ) );
  218. }
  219. if ( $this->properties['max'] === null )
  220. {
  221. $this->properties['max'] = ceil( log( $this->properties['maxValue'], $this->properties['base'] ) );
  222. }
  223. $this->properties['minorStep'] = 1;
  224. if ( ( $modifier = ( ( $this->properties['max'] - $this->properties['min'] ) / self::MAX_STEPS ) ) > 1 )
  225. {
  226. $this->properties['majorStep'] = $modifier = ceil( $modifier );
  227. $this->properties['min'] = floor( $this->properties['min'] / $modifier ) * $modifier;
  228. $this->properties['max'] = floor( $this->properties['max'] / $modifier ) * $modifier;
  229. }
  230. else
  231. {
  232. $this->properties['majorStep'] = 1;
  233. }
  234. }
  235. /**
  236. * Get coordinate for a dedicated value on the chart
  237. *
  238. * @param float $value Value to determine position for
  239. * @return float Position on chart
  240. */
  241. public function getCoordinate( $value )
  242. {
  243. // Force typecast, because ( false < -100 ) results in (bool) true
  244. $floatValue = (float) $value;
  245. if ( $value === false )
  246. {
  247. switch ( $this->position )
  248. {
  249. case ezcGraph::LEFT:
  250. case ezcGraph::TOP:
  251. return 0.;
  252. case ezcGraph::RIGHT:
  253. case ezcGraph::BOTTOM:
  254. return 1.;
  255. }
  256. }
  257. else
  258. {
  259. $position = ( log( $value, $this->properties['base'] ) - $this->properties['min'] ) / ( $this->properties['max'] - $this->properties['min'] );
  260. switch ( $this->position )
  261. {
  262. case ezcGraph::LEFT:
  263. case ezcGraph::TOP:
  264. return $position;
  265. case ezcGraph::RIGHT:
  266. case ezcGraph::BOTTOM:
  267. return 1 - $position;
  268. }
  269. }
  270. }
  271. /**
  272. * Return count of minor steps
  273. *
  274. * @return integer Count of minor steps
  275. */
  276. public function getMinorStepCount()
  277. {
  278. return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['minorStep'] );
  279. }
  280. /**
  281. * Return count of major steps
  282. *
  283. * @return integer Count of major steps
  284. */
  285. public function getMajorStepCount()
  286. {
  287. return (int) ( ( $this->properties['max'] - $this->properties['min'] ) / $this->properties['majorStep'] );
  288. }
  289. /**
  290. * Get label for a dedicated step on the axis
  291. *
  292. * @param integer $step Number of step
  293. * @return string label
  294. */
  295. public function getLabel( $step )
  296. {
  297. if ( $this->properties['labelCallback'] !== null )
  298. {
  299. return call_user_func_array(
  300. $this->properties['labelCallback'],
  301. array(
  302. sprintf(
  303. $this->properties['logarithmicalFormatString'],
  304. $this->properties['base'],
  305. $this->properties['min'] + ( $step * $this->properties['majorStep'] )
  306. ),
  307. $step,
  308. )
  309. );
  310. }
  311. else
  312. {
  313. return sprintf(
  314. $this->properties['logarithmicalFormatString'],
  315. $this->properties['base'],
  316. $this->properties['min'] + ( $step * $this->properties['majorStep'] )
  317. );
  318. }
  319. }
  320. /**
  321. * Is zero step
  322. *
  323. * Returns true if the given step is the one on the initial axis position
  324. *
  325. * @param int $step Number of step
  326. * @return bool Status If given step is initial axis position
  327. */
  328. public function isZeroStep( $step )
  329. {
  330. return ( $step == 0 );
  331. }
  332. }
  333. ?>