properties['majorStepCount'] = false; $this->properties['minorStepCount'] = false; $this->properties['majorStepSize'] = 3; $this->properties['minorStepSize'] = 1; $this->properties['innerStep'] = true; $this->properties['outerStep'] = false; $this->properties['outerGrid'] = false; $this->properties['showLabels'] = true; $this->properties['labelPadding'] = 2; parent::__construct( $options ); } /** * __set * * @param mixed $propertyName * @param mixed $propertyValue * @throws ezcBaseValueException * If a submitted parameter was out of range or type. * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @return void * @ignore */ public function __set( $propertyName, $propertyValue ) { switch ( $propertyName ) { case 'driver': if ( $propertyValue instanceof ezcGraphDriver ) { $this->properties['driver'] = $propertyValue; } else { throw new ezcGraphInvalidDriverException( $propertyValue ); } break; case 'majorStepCount': if ( ( $propertyValue !== false ) && !is_numeric( $propertyValue ) || ( $propertyValue < 0 ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); } $this->properties['majorStepCount'] = (int) $propertyValue; break; case 'minorStepCount': if ( ( $propertyValue !== false ) && !is_numeric( $propertyValue ) || ( $propertyValue < 0 ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); } $this->properties['minorStepCount'] = (int) $propertyValue; break; case 'majorStepSize': if ( !is_numeric( $propertyValue ) || ( $propertyValue < 0 ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); } $this->properties['majorStepSize'] = (int) $propertyValue; break; case 'minorStepSize': if ( !is_numeric( $propertyValue ) || ( $propertyValue < 0 ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); } $this->properties['minorStepSize'] = (int) $propertyValue; break; case 'innerStep': if ( !is_bool( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); } $this->properties['innerStep'] = (bool) $propertyValue; break; case 'outerStep': if ( !is_bool( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); } $this->properties['outerStep'] = (bool) $propertyValue; break; case 'outerGrid': if ( !is_bool( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); } $this->properties['outerGrid'] = (bool) $propertyValue; break; case 'showLabels': if ( !is_bool( $propertyValue ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); } $this->properties['showLabels'] = (bool) $propertyValue; break; case 'labelPadding': if ( !is_numeric( $propertyValue ) || ( $propertyValue < 0 ) ) { throw new ezcBaseValueException( $propertyName, $propertyValue, 'int >= 0' ); } $this->properties['labelPadding'] = (int) $propertyValue; break; default: throw new ezcBasePropertyNotFoundException( $propertyName ); } } public function determineLineCuttingPoint( ezcGraphCoordinate $aStart, ezcGraphCoordinate $aDir, ezcGraphCoordinate $bStart, ezcGraphCoordinate $bDir ) { // Check if lines are parallel if ( ( ( $aDir->x == 0 ) && ( $bDir->x == 0 ) ) || ( ( $aDir->y == 0 ) && ( $bDir->y == 0 ) ) || ( ( $aDir->x * $bDir->x * $aDir->y * $bDir->y != 0 ) && ( ( $aDir->x / $aDir->y ) == ( $bDir->x / $bDir->y ) ) ) ) { return false; } // Use ? : to prevent division by zero $denominator = ( $aDir->y != 0 ? $bDir->y / $aDir->y : 0 ) - ( $aDir->x != 0 ? $bDir->x / $aDir->x : 0 ); // Solve equatation if ( $denominator == 0 ) { return - ( ( $aDir->y != 0 ? $bStart->y / $aDir->y : 0 ) - ( $aDir->y != 0 ? $aStart->y / $aDir->y : 0 ) - ( $aDir->x != 0 ? $bStart->x / $aDir->x : 0 ) + ( $aDir->x != 0 ? $aStart->x / $aDir->x : 0 ) ); } else { return - ( ( $aDir->y != 0 ? $bStart->y / $aDir->y : 0 ) - ( $aDir->y != 0 ? $aStart->y / $aDir->y : 0 ) - ( $aDir->x != 0 ? $bStart->x / $aDir->x : 0 ) + ( $aDir->x != 0 ? $aStart->x / $aDir->x : 0 ) ) / $denominator; } } /** * Draw single step on a axis * * Draws a step on a axis at the current position * * @param ezcGraphRenderer $renderer Renderer to draw the step with * @param ezcGraphCoordinate $position Position of step * @param ezcGraphCoordinate $direction Direction of axis * @param int $axisPosition Position of axis * @param int $size Step size * @param ezcGraphColor $color Color of axis * @return void */ public function drawStep( ezcGraphRenderer $renderer, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, $axisPosition, $size, ezcGraphColor $color ) { if ( ! ( $this->innerStep || $this->outerStep ) ) { return false; } $drawStep = false; if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) || ( ( $axisPosition === ezcGraph::BOTTOM ) && $this->outerStep ) || ( ( $axisPosition === ezcGraph::TOP ) && $this->innerStep ) || ( ( $axisPosition === ezcGraph::RIGHT ) && $this->outerStep ) || ( ( $axisPosition === ezcGraph::LEFT ) && $this->innerStep ) ) { // Turn direction vector to left by 90 degrees and multiply // with major step size $stepStart = new ezcGraphCoordinate( $position->x - $direction->y * $size, $position->y + $direction->x * $size ); $drawStep = true; } else { $stepStart = $position; } if ( ( ( $axisPosition === ezcGraph::CENTER ) && $this->innerStep ) || ( ( $axisPosition === ezcGraph::BOTTOM ) && $this->innerStep ) || ( ( $axisPosition === ezcGraph::TOP ) && $this->outerStep ) || ( ( $axisPosition === ezcGraph::RIGHT ) && $this->innerStep ) || ( ( $axisPosition === ezcGraph::LEFT ) && $this->outerStep ) ) { // Turn direction vector to right by 90 degrees and multiply // with major step size $stepEnd = new ezcGraphCoordinate( $position->x + $direction->y * $size, $position->y - $direction->x * $size ); $drawStep = true; } else { $stepEnd = $position; } if ( $drawStep ) { $renderer->drawStepLine( $stepStart, $stepEnd, $color ); } } /** * Draw grid * * Draws a grid line at the current position * * @param ezcGraphRenderer $renderer Renderer to draw the grid with * @param ezcGraphBoundings $boundings Boundings of axis * @param ezcGraphCoordinate $position Position of step * @param ezcGraphCoordinate $direction Direction of axis * @param ezcGraphColor $color Color of axis * @return void */ protected function drawGrid( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color ) { // Direction of grid line is direction of axis turned right by 90 // degrees $gridDirection = new ezcGraphCoordinate( $direction->y, - $direction->x ); $cuttingPoints = array(); foreach ( array( // Bounding lines array( 'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ), 'dir' => new ezcGraphCoordinate( 0, $boundings->y1 - $boundings->y0 ) ), array( 'start' => new ezcGraphCoordinate( $boundings->x0, $boundings->y0 ), 'dir' => new ezcGraphCoordinate( $boundings->x1 - $boundings->x0, 0 ) ), array( 'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ), 'dir' => new ezcGraphCoordinate( 0, $boundings->y0 - $boundings->y1 ) ), array( 'start' => new ezcGraphCoordinate( $boundings->x1, $boundings->y1 ), 'dir' => new ezcGraphCoordinate( $boundings->x0 - $boundings->x1, 0 ) ), ) as $boundingLine ) { // Test for cutting points with bounding lines, where cutting // position is between 0 and 1, which means, that the line is hit // on the bounding box rectangle. Use these points as a start and // ending point for the grid lines. There should *always* be two // points returned. $cuttingPosition = $this->determineLineCuttingPoint( $boundingLine['start'], $boundingLine['dir'], $position, $gridDirection ); if ( $cuttingPosition === false ) { continue; } // Round to prevent minor float incorectnesses $cuttingPosition = abs( round( $cuttingPosition, 2 ) ); if ( ( $cuttingPosition >= 0 ) && ( $cuttingPosition <= 1 ) ) { $cuttingPoints[] = new ezcGraphCoordinate( $boundingLine['start']->x + $cuttingPosition * $boundingLine['dir']->x, $boundingLine['start']->y + $cuttingPosition * $boundingLine['dir']->y ); } } if ( count( $cuttingPoints ) < 2 ) { return false; } // Finally draw grid line $renderer->drawGridLine( $cuttingPoints[0], $cuttingPoints[1], $color ); } /** * Modify chart boundings * * Optionally modify boundings of chart data * * @param ezcGraphBoundings $boundings Current boundings of chart * @param ezcGraphCoordinate $direction Direction of the current axis * @return ezcGraphBoundings Modified boundings */ public function modifyChartBoundings( ezcGraphBoundings $boundings, ezcGraphCoordinate $direction ) { return $boundings; } /** * Modify chart data position * * Optionally additionally modify the coodinate of a data point * * @param ezcGraphCoordinate $coordinate Data point coordinate * @return ezcGraphCoordinate Modified coordinate */ public function modifyChartDataPosition( ezcGraphCoordinate $coordinate ) { return $coordinate; } /** * Render Axis labels * * Render labels for an axis. * * @param ezcGraphRenderer $renderer Renderer used to draw the chart * @param ezcGraphBoundings $boundings Boundings of the axis * @param ezcGraphCoordinate $start Axis starting point * @param ezcGraphCoordinate $end Axis ending point * @param ezcGraphChartElementAxis $axis Axis instance * @return void */ abstract public function renderLabels( ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphChartElementAxis $axis ); } ?>