/** * Render the text * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Boundings for the axis * @return ezcGraphBoundings Remaining boundings */ public function render(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { $height = (int) min(round($this->properties['maxHeight'] * ($boundings->y1 - $boundings->y0)), $this->properties['font']->maxFontSize + $this->padding * 2 + $this->margin * 2); switch ($this->properties['position']) { case ezcGraph::TOP: $textBoundings = new ezcGraphBoundings($boundings->x0, $boundings->y0, $boundings->x1, $boundings->y0 + $height); $boundings->y0 += $height + $this->properties['margin']; break; case ezcGraph::BOTTOM: $textBoundings = new ezcGraphBoundings($boundings->x0, $boundings->y1 - $height, $boundings->x1, $boundings->y1); $boundings->y1 -= $height + $this->properties['margin']; break; } $textBoundings = $renderer->drawBox($textBoundings, $this->properties['background'], $this->properties['border'], $this->properties['borderWidth'], $this->properties['margin'], $this->properties['padding']); $renderer->drawText($textBoundings, $this->properties['title'], ezcGraph::CENTER | ezcGraph::MIDDLE); return $boundings; }
/** * 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 */ public function renderLabels(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphChartElementAxis $axis) { // receive rendering parameters from axis $steps = $axis->getSteps(); $this->steps = $steps; $axisBoundings = new ezcGraphBoundings($start->x, $start->y, $end->x, $end->y); // Determine normalized axis direction $this->direction = new ezcGraphVector($start->x - $end->x, $start->y - $end->y); $this->direction->unify(); if ($this->outerGrid) { $gridBoundings = $boundings; } else { $gridBoundings = new ezcGraphBoundings($boundings->x0 + $renderer->xAxisSpace * abs($this->direction->y), $boundings->y0 + $renderer->yAxisSpace * abs($this->direction->x), $boundings->x1 - $renderer->xAxisSpace * abs($this->direction->y), $boundings->y1 - $renderer->yAxisSpace * abs($this->direction->x)); } // Determine additional required axis space by boxes $firstStep = reset($steps); $lastStep = end($steps); $this->widthModifier = 1 + $firstStep->width / 2 + $lastStep->width / 2; // Draw steps and grid foreach ($steps as $nr => $step) { $position = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * ($step->position + $step->width) / $this->widthModifier, $start->y + ($end->y - $start->y) * ($step->position + $step->width) / $this->widthModifier); $stepWidth = $step->width / $this->widthModifier; $stepSize = new ezcGraphCoordinate($axisBoundings->width * $stepWidth, $axisBoundings->height * $stepWidth); if ($this->showLabels) { // Calculate label boundings switch (true) { case abs($this->direction->x) > abs($this->direction->y) && $this->direction->x <= 0: $labelBoundings = new ezcGraphBoundings($position->x - $stepSize->x + $this->labelPadding, $position->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $renderer->yAxisSpace - $this->labelPadding); $alignement = ezcGraph::CENTER | ezcGraph::TOP; break; case abs($this->direction->x) > abs($this->direction->y) && $this->direction->x > 0: $labelBoundings = new ezcGraphBoundings($position->x + $this->labelPadding, $position->y + $this->labelPadding, $position->x + $stepSize->x - $this->labelPadding, $position->y + $renderer->yAxisSpace - $this->labelPadding); $alignement = ezcGraph::CENTER | ezcGraph::TOP; break; case $this->direction->y <= 0: $labelBoundings = new ezcGraphBoundings($position->x - $renderer->xAxisSpace + $this->labelPadding, $position->y - $stepSize->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y - $this->labelPadding); $alignement = ezcGraph::MIDDLE | ezcGraph::RIGHT; break; case $this->direction->y > 0: $labelBoundings = new ezcGraphBoundings($position->x - $renderer->xAxisSpace + $this->labelPadding, $position->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $stepSize->y - $this->labelPadding); $alignement = ezcGraph::MIDDLE | ezcGraph::RIGHT; break; } $renderer->drawText($labelBoundings, $step->label, $alignement); } // major grid if ($axis->majorGrid) { $this->drawGrid($renderer, $gridBoundings, $position, $stepSize, $axis->majorGrid); } // major step $this->drawStep($renderer, $position, $this->direction, $axis->position, $this->majorStepSize, $axis->border); } }
/** * Render the assigned data * * Will renderer all charts data in the remaining boundings after drawing * all other chart elements. The data will be rendered depending on the * settings in the dataset. * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Remaining boundings * @return void */ protected function renderData(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { // Only draw the first (and only) dataset $dataset = $this->data->rewind(); $datasetName = $this->data->key(); $this->driver->options->font = $this->options->font; // Calculate sum of all values to be able to calculate percentage $sum = 0; foreach ($dataset as $name => $value) { if ($value < 0) { throw new ezcGraphInvalidDataException("Values >= 0 required, '{$name}' => '{$value}'."); } $sum += $value; } if ($this->options->sum !== false) { $sum = max($sum, $this->options->sum); } if ($sum <= 0) { throw new ezcGraphInvalidDataException("Pie charts require a value sum > 0, your value: '{$sum}'."); } $angle = 0; foreach ($dataset as $label => $value) { // Skip rendering values which equals 0 if ($value <= 0) { continue; } switch ($dataset->displayType->default) { case ezcGraph::PIE: $displayLabel = $this->options->labelCallback !== null ? call_user_func($this->options->labelCallback, $label, $value, $value / $sum) : sprintf($this->options->label, $label, $value, $value / $sum * 100); $renderer->drawPieSegment($boundings, new ezcGraphContext($datasetName, $label, $dataset->url[$label]), $dataset->color[$label], $angle, $angle += $value / $sum * 360, $displayLabel, $dataset->highlight[$label]); break; default: throw new ezcGraphInvalidDisplayTypeException($dataset->displayType->default); break; } } }
/** * Reset renderer properties * * Reset all renderer properties, which were calculated during the * rendering process, to offer a clean environment for rerendering. * * @return void */ protected function resetRenderer() { parent::resetRenderer(); // Also reset special 2D renderer options $this->pieSegmentLabels = array(0 => array(), 1 => array()); $this->pieSegmentBoundings = false; $this->linePostSymbols = array(); $this->axisLabels = array(); $this->circleSectors = array(); }
/** * Render the background * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Boundings * @return ezcGraphBoundings Remaining boundings */ public function render(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { $boundings = $renderer->drawBox($boundings, $this->background, $this->border, $this->borderWidth, $this->margin, $this->padding); if ($this->image === false) { return $boundings; } $renderer->drawBackgroundImage($boundings, $this->image, $this->position, $this->repeat); return $boundings; }
/** * Render the assigned data * * Will renderer all charts data in the remaining boundings after drawing * all other chart elements. The data will be rendered depending on the * settings in the dataset. * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Remaining boundings * @return void */ protected function renderData(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphBoundings $innerBoundings) { // Use inner boundings for drawning chart data $boundings = $innerBoundings; $yAxisNullPosition = $this->elements['xAxis']->getCoordinate(false); // Initialize counters $nr = array(); $count = array(); foreach ($this->data as $data) { if (!isset($nr[$data->displayType->default])) { $nr[$data->displayType->default] = 0; $count[$data->displayType->default] = 0; } $nr[$data->displayType->default]++; $count[$data->displayType->default]++; } $checkedRegularSteps = false; // Display data foreach ($this->data as $datasetName => $data) { --$nr[$data->displayType->default]; // Check which axis should be used $xAxis = $data->xAxis->default ? $data->xAxis->default : $this->elements['xAxis']; $yAxis = $data->yAxis->default ? $data->yAxis->default : $this->elements['yAxis']; // Determine fill color for dataset if ($this->options->fillLines !== false) { $fillColor = clone $data->color->default; $fillColor->alpha = (int) round((255 - $fillColor->alpha) * ($this->options->fillLines / 255)); } else { $fillColor = null; } // Ensure regular steps on axis when used with bar charts and // precalculate some values use to render bar charts // // Called only once and only when bars should be rendered if ($checkedRegularSteps === false && $data->displayType->default === ezcGraph::BAR) { $height = $this->calculateStepWidth($yAxis, $xAxis, $boundings->height)->y; } // Draw lines for dataset $lastPoint = false; foreach ($data as $key => $value) { // Calculate point in chart $point = $xAxis->axisLabelRenderer->modifyChartDataPosition($yAxis->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate($xAxis->getCoordinate($value), $yAxis->getCoordinate($key)))); // Render depending on display type of dataset switch (true) { case $data->displayType->default === ezcGraph::BAR: $renderer->drawHorizontalBar($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $data->color[$key], $point, $height, $nr[$data->displayType->default], $count[$data->displayType->default], $data->symbol[$key], $yAxisNullPosition); // Render highlight string if requested if ($data->highlight[$key]) { $renderer->drawDataHighlightText($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $point, $yAxisNullPosition, $nr[$data->displayType->default], $count[$data->displayType->default], $this->options->highlightFont, $data->highlightValue[$key] ? $data->highlightValue[$key] : $value, $this->options->highlightSize + $this->options->highlightFont->padding * 2, $this->options->highlightLines ? $data->color[$key] : null, $this->options->highlightXOffset ? $this->options->highlightXOffset : 0, $this->options->highlightYOffset ? $this->options->highlightYOffset : 0, $height, $data->displayType->default); } break; default: throw new ezcGraphInvalidDisplayTypeException($data->displayType->default); break; } // Store last point, used to connect lines in line chart. $lastPoint = $point; } } }
/** * Render a legend * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Boundings for the axis * @return ezcGraphBoundings Remaining boundings */ public function render(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { $boundings = $this->calculateBoundings($boundings); if ($this->position === ezcGraph::LEFT || $this->position === ezcGraph::RIGHT) { $type = ezcGraph::VERTICAL; } else { $type = ezcGraph::HORIZONTAL; } // Render standard elements $this->properties['boundings'] = $renderer->drawBox($this->properties['boundings'], $this->properties['background'], $this->properties['border'], $this->properties['borderWidth'], $this->properties['margin'], $this->properties['padding'], $this->properties['title'], $this->getTitleSize($this->properties['boundings'], $type)); // Render legend $renderer->drawLegend($this->boundings, $this, $type); return $boundings; }
/** * 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(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 // exactly 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) { // This should not happpen return false; } // Finally draw grid line $renderer->drawGridLine($cuttingPoints[0], $cuttingPoints[1], $color); }
/** * Reset renderer properties * * Reset all renderer properties, which were calculated during the * rendering process, to offer a clean environment for rerendering. * * @return void */ protected function resetRenderer() { parent::resetRenderer(); // Also reset special 3D renderer options $this->pieSegmentLabels = array(0 => array(), 1 => array()); $this->pieSegmentBoundings = false; $this->linePostSymbols = array(); $this->frontLines = array(); $this->circleSectors = array(); $this->barPostProcessing = array(); $this->depth = false; $this->xDepthFactor = false; $this->yDepthFactor = false; $this->dataBoundings = false; $this->axisLabels = array(); }
/** * 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 */ public function renderLabels(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphChartElementAxis $axis) { // receive rendering parameters from axis $steps = $axis->getSteps(); $this->steps = $steps; $axisBoundings = new ezcGraphBoundings($start->x, $start->y, $end->x, $end->y); // Determine normalized axis direction $this->direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y); $this->direction->unify(); $axisAngle = -$this->direction->angle(new ezcGraphVector(1, 0)); if ($this->outerGrid) { $gridBoundings = $boundings; } else { $gridBoundings = new ezcGraphBoundings($boundings->x0 + $renderer->xAxisSpace, $boundings->y0 + $renderer->yAxisSpace, $boundings->x1 - $renderer->xAxisSpace, $boundings->y1 - $renderer->yAxisSpace); } // Determine optimal angle if none specified if ($this->angle === null) { $minimumStepWidth = null; foreach ($steps as $nr => $step) { if ($minimumStepWidth === null || $step->width < $minimumStepWidth) { $minimumStepWidth = $step->width; } } $width = abs($axisBoundings->width * $minimumStepWidth * $this->direction->x + $axisBoundings->height * $minimumStepWidth * $this->direction->y); $height = abs($renderer->yAxisSpace * $this->direction->x + $renderer->xAxisSpace * $this->direction->y); $length = sqrt(pow($width, 2) + pow($height, 2)); $this->angle = rad2deg(acos($height / $length)); } // Determine additional required axis space by boxes $firstStep = reset($steps); $lastStep = end($steps); $textAngle = $axisAngle + deg2rad($this->angle) + ($axis->position & (ezcGraph::TOP | ezcGraph::BOTTOM) ? deg2rad(270) : deg2rad(90)); // Ensure angle between 0 and 360 degrees $degTextAngle = rad2deg($textAngle); while ($degTextAngle < 0) { $degTextAngle += 360.0; } $this->offset = ($this->angle < 0 ? -1 : 1) * ($axis->position & (ezcGraph::TOP | ezcGraph::LEFT) ? 1 : -1) * (1 - cos(deg2rad($this->angle * 2))); $axisSpaceFactor = abs(($this->direction->x == 0 ? 0 : $this->direction->x * $renderer->yAxisSpace / $axisBoundings->width) + ($this->direction->y == 0 ? 0 : $this->direction->y * $renderer->xAxisSpace / $axisBoundings->height)); $start = new ezcGraphCoordinate($start->x + max(0.0, $axisSpaceFactor * $this->offset) * ($end->x - $start->x), $start->y + max(0.0, $axisSpaceFactor * $this->offset) * ($end->y - $start->y)); $end = new ezcGraphCoordinate($end->x + min(0.0, $axisSpaceFactor * $this->offset) * ($end->x - $start->x), $end->y + min(0.0, $axisSpaceFactor * $this->offset) * ($end->y - $start->y)); $labelLength = sqrt(pow($renderer->xAxisSpace * $this->direction->y + $axisSpaceFactor * $this->offset * ($end->x - $start->x), 2) + pow($renderer->yAxisSpace * $this->direction->x + $axisSpaceFactor * $this->offset * ($end->y - $start->y), 2)); $this->offset *= $axisSpaceFactor; // Draw steps and grid foreach ($steps as $nr => $step) { $position = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $step->position * abs($this->direction->x), $start->y + ($end->y - $start->y) * $step->position * abs($this->direction->y)); $stepSize = new ezcGraphCoordinate(($end->x - $start->x) * $step->width, ($end->y - $start->y) * $step->width); // Calculate label boundings switch (true) { case $nr === 0: $labelSize = min(abs($renderer->xAxisSpace * 2 * $this->direction->x + $renderer->yAxisSpace * 2 * $this->direction->y), abs($step->width * $axisBoundings->width * $this->direction->x + $step->width * $axisBoundings->height * $this->direction->y)); break; case $step->isLast: $labelSize = min(abs($renderer->xAxisSpace * 2 * $this->direction->x + $renderer->yAxisSpace * 2 * $this->direction->y), abs($steps[$nr - 1]->width * $axisBoundings->width * $this->direction->x + $steps[$nr - 1]->width * $axisBoundings->height * $this->direction->y)); break; default: $labelSize = min(abs($step->width * $axisBoundings->width * $this->direction->x + $step->width * $axisBoundings->height * $this->direction->y), abs($steps[$nr - 1]->width * $axisBoundings->width * $this->direction->x + $steps[$nr - 1]->width * $axisBoundings->height * $this->direction->y)); break; } $labelSize = $labelSize * cos(deg2rad($this->angle)); $lengthReducement = min(abs(tan(deg2rad($this->angle)) * ($labelSize / 2)), abs($labelLength / 2)); switch (true) { case $degTextAngle >= 0 && $degTextAngle < 90 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 270 && $degTextAngle < 360 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x, $position->y, $position->x + abs($labelLength) - $lengthReducement, $position->y + $labelSize); $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; $labelRotation = $degTextAngle; break; case $degTextAngle >= 90 && $degTextAngle < 180 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 180 && $degTextAngle < 270 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x - abs($labelLength) + $lengthReducement, $position->y, $position->x, $position->y + $labelSize); $labelAlignement = ezcGraph::RIGHT | ezcGraph::TOP; $labelRotation = $degTextAngle - 180; break; case $degTextAngle >= 180 && $degTextAngle < 270 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 90 && $degTextAngle < 180 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x - abs($labelLength) + $lengthReducement, $position->y - $labelSize, $position->x, $position->y); $labelAlignement = ezcGraph::RIGHT | ezcGraph::BOTTOM; $labelRotation = $degTextAngle - 180; break; case $degTextAngle >= 270 && $degTextAngle < 360 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 0 && $degTextAngle < 90 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x, $position->y + $labelSize, $position->x + abs($labelLength) - $lengthReducement, $position->y); $labelAlignement = ezcGraph::LEFT | ezcGraph::BOTTOM; $labelRotation = $degTextAngle; break; } $renderer->drawText($labelBoundings, $step->label, $labelAlignement, new ezcGraphRotation($labelRotation, $position)); // major grid if ($axis->majorGrid) { $this->drawGrid($renderer, $gridBoundings, $position, $stepSize, $axis->majorGrid); } // major step $this->drawStep($renderer, $position, $this->direction, $axis->position, $this->majorStepSize, $axis->border); } }
/** * 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 * @param int $stepPosition * @return void */ protected function drawGrid(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color, $stepPosition = null) { // Calculate position on last axis $start = new ezcGraphCoordinate($boundings->x0 + ($width = $boundings->width / 2), $boundings->y0 + ($height = $boundings->height / 2)); $lastAngle = $this->lastStep * 2 * M_PI; $end = new ezcGraphCoordinate($start->x + sin($lastAngle) * $width, $start->y - cos($lastAngle) * $height); $direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y); $direction->unify(); // Convert elipse to circle for correct angle calculation $direction->y *= $renderer->xAxisSpace / $renderer->yAxisSpace; $angle = $direction->angle(new ezcGraphVector(0, 1)); $movement = new ezcGraphVector(sin($angle) * $renderer->xAxisSpace * ($direction->x < 0 ? -1 : 1), cos($angle) * $renderer->yAxisSpace); $start->x += $movement->x; $start->y += $movement->y; $end->x -= $movement->x; $end->y -= $movement->y; $lastPosition = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $stepPosition, $start->y + ($end->y - $start->y) * $stepPosition); $renderer->drawGridLine($position, $lastPosition, $color); }
/** * Render the axis * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Boundings for the axis * @return ezcGraphBoundings Remaining boundings */ public function render(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { switch ($this->position) { case ezcGraph::TOP: $start = new ezcGraphCoordinate(($boundings->x1 - $boundings->x0) * $this->axisSpace + $this->nullPosition * ($boundings->x1 - $boundings->x0) * (1 - 2 * $this->axisSpace), 0); $end = new ezcGraphCoordinate(($boundings->x1 - $boundings->x0) * $this->axisSpace + $this->nullPosition * ($boundings->x1 - $boundings->x0) * (1 - 2 * $this->axisSpace), $boundings->y1 - $boundings->y0); break; case ezcGraph::BOTTOM: $start = new ezcGraphCoordinate(($boundings->x1 - $boundings->x0) * $this->axisSpace + $this->nullPosition * ($boundings->x1 - $boundings->x0) * (1 - 2 * $this->axisSpace), $boundings->y1 - $boundings->y0); $end = new ezcGraphCoordinate(($boundings->x1 - $boundings->x0) * $this->axisSpace + $this->nullPosition * ($boundings->x1 - $boundings->x0) * (1 - 2 * $this->axisSpace), 0); break; case ezcGraph::LEFT: $start = new ezcGraphCoordinate(0, ($boundings->y1 - $boundings->y0) * $this->axisSpace + $this->nullPosition * ($boundings->y1 - $boundings->y0) * (1 - 2 * $this->axisSpace)); $end = new ezcGraphCoordinate($boundings->x1 - $boundings->x0, ($boundings->y1 - $boundings->y0) * $this->axisSpace + $this->nullPosition * ($boundings->y1 - $boundings->y0) * (1 - 2 * $this->axisSpace)); break; case ezcGraph::RIGHT: $start = new ezcGraphCoordinate($boundings->x1 - $boundings->x0, ($boundings->y1 - $boundings->y0) * $this->axisSpace + $this->nullPosition * ($boundings->y1 - $boundings->y0) * (1 - 2 * $this->axisSpace)); $end = new ezcGraphCoordinate(0, ($boundings->y1 - $boundings->y0) * $this->axisSpace + $this->nullPosition * ($boundings->y1 - $boundings->y0) * (1 - 2 * $this->axisSpace)); break; } $renderer->drawAxis($boundings, $start, $end, $this, $this->axisLabelRenderer); return $boundings; }
/** * Render label text. * * Render the text of a single label, depending on the position, length and * rotation of the label. * * @param ezcGraphRenderer $renderer * @param ezcGraphChartElementAxis $axis * @param ezcGraphCoordinate $position * @param string $label * @param float $degTextAngle * @param float $labelLength * @param float $labelSize * @param float $lengthReducement * @return void */ protected function renderLabelText(ezcGraphRenderer $renderer, ezcGraphChartElementAxis $axis, ezcGraphCoordinate $position, $label, $degTextAngle, $labelLength, $labelSize, $lengthReducement) { switch (true) { case $degTextAngle >= 0 && $degTextAngle < 90 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 270 && $degTextAngle < 360 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x, $position->y, $position->x + abs($labelLength) - $lengthReducement, $position->y + $labelSize); $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; $labelRotation = $degTextAngle; break; case $degTextAngle >= 90 && $degTextAngle < 180 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 180 && $degTextAngle < 270 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x - abs($labelLength) + $lengthReducement, $position->y, $position->x, $position->y + $labelSize); $labelAlignement = ezcGraph::RIGHT | ezcGraph::TOP; $labelRotation = $degTextAngle - 180; break; case $degTextAngle >= 180 && $degTextAngle < 270 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 90 && $degTextAngle < 180 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x - abs($labelLength) + $lengthReducement, $position->y - $labelSize, $position->x, $position->y); $labelAlignement = ezcGraph::RIGHT | ezcGraph::BOTTOM; $labelRotation = $degTextAngle - 180; break; case $degTextAngle >= 270 && $degTextAngle < 360 && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT) || $degTextAngle >= 0 && $degTextAngle < 90 && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM): $labelBoundings = new ezcGraphBoundings($position->x, $position->y, $position->x - abs($labelLength) + $lengthReducement, $position->y + $labelSize); $labelAlignement = ezcGraph::LEFT | ezcGraph::TOP; $labelRotation = $degTextAngle; break; } $renderer->drawText($labelBoundings, $label, $labelAlignement, new ezcGraphRotation($labelRotation, $position)); }
/** * Render the assigned data * * Will renderer all charts data in the remaining boundings after drawing * all other chart elements. The data will be rendered depending on the * settings in the dataset. * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Remaining boundings * @return void */ protected function renderData(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { // Apply axis space $xAxisSpace = ($boundings->x1 - $boundings->x0) * $this->axis->axisSpace; $yAxisSpace = ($boundings->y1 - $boundings->y0) * $this->axis->axisSpace; $center = new ezcGraphCoordinate($boundings->width / 2, $boundings->height / 2); // We do not differentiate between display types in radar charts. $nr = $count = count($this->data); // Draw axis at major steps of virtual axis $steps = $this->elements['rotationAxis']->getSteps(); $lastStepPosition = null; $axisColor = $this->elements['axis']->border; foreach ($steps as $step) { $this->elements['axis']->label = $step->label; $this->drawRotatedAxis($this->elements['axis'], $boundings, $center, $step->position, $lastStepPosition); $lastStepPosition = $step->position; if (count($step->childs)) { foreach ($step->childs as $childStep) { $this->elements['axis']->label = null; $this->elements['axis']->border = $this->childAxisColor; $this->drawRotatedAxis($this->elements['axis'], $boundings, $center, $childStep->position, $lastStepPosition); $lastStepPosition = $childStep->position; } } $this->elements['axis']->border = $axisColor; } // Display data $this->elements['axis']->position = ezcGraph::TOP; foreach ($this->data as $datasetName => $data) { --$nr; // Determine fill color for dataset if ($this->options->fillLines !== false) { $fillColor = clone $data->color->default; $fillColor->alpha = (int) round((255 - $fillColor->alpha) * ($this->options->fillLines / 255)); } else { $fillColor = null; } // Draw lines for dataset $lastPoint = false; foreach ($data as $key => $value) { $point = new ezcGraphCoordinate($this->elements['rotationAxis']->getCoordinate($key), $this->elements['axis']->getCoordinate($value)); /* Transformation required for 3d like renderers ... * which axis should transform here? $point = $this->elements['xAxis']->axisLabelRenderer->modifyChartDataPosition( $this->elements['yAxis']->axisLabelRenderer->modifyChartDataPosition( new ezcGraphCoordinate( $this->elements['xAxis']->getCoordinate( $key ), $this->elements['yAxis']->getCoordinate( $value ) ) ) ); // */ $renderer->drawRadarDataLine($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $data->color->default, clone $center, $lastPoint === false ? $point : $lastPoint, $point, $nr, $count, $data->symbol[$key], $data->color[$key], $fillColor, $this->options->lineThickness); $lastPoint = $point; } } }
/** * Render the assigned data * * Will renderer all charts data in the remaining boundings after drawing * all other chart elements. The data will be rendered depending on the * settings in the dataset. * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Remaining boundings * @return void */ protected function renderData(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings) { // Draw the odometer data $dataset = $this->data->rewind(); foreach ($dataset as $key => $value) { $renderer->drawOdometerMarker($boundings, $this->elements['axis']->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate($this->elements['axis']->getCoordinate($value), 0)), $dataset->symbol[$key], $dataset->color[$key], $this->options->markerWidth); } }
/** * Draw rectangular grid * * Draws a grid line at the current position for rectangular directed axis. * * Method special for rectangularly directed axis to minimize the floating * point calculation inaccuracies. Those are not necessary for rectangles, * while for non-rectangular directed axis. * * @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 drawRectangularGrid(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphCoordinate $position, ezcGraphCoordinate $direction, ezcGraphColor $color) { if (abs($direction->x) < 1.0E-5) { $renderer->drawGridLine(new ezcGraphCoordinate($boundings->x0, $position->y), new ezcGraphCoordinate($boundings->x1, $position->y), $color); } else { $renderer->drawGridLine(new ezcGraphCoordinate($position->x, $boundings->y0), new ezcGraphCoordinate($position->x, $boundings->y1), $color); } }
/** * Render the axis * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Boundings for the axis * @return ezcGraphBoundings Remaining boundings */ public function render(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphBoundings $innerBoundings = null) { $this->innerBoundings = $innerBoundings; $startSpace = $this->axisSpace; $endSpace = $this->outerAxisSpace === null ? $this->axisSpace : $this->outerAxisSpace; switch ($this->position) { case ezcGraph::TOP: $start = new ezcGraphCoordinate($boundings->width * $startSpace + $this->nullPosition * $boundings->width * (1 - ($startSpace + $endSpace)), 0); $end = new ezcGraphCoordinate($boundings->width * $startSpace + $this->nullPosition * $boundings->width * (1 - ($startSpace + $endSpace)), $boundings->height); break; case ezcGraph::BOTTOM: $start = new ezcGraphCoordinate($boundings->width * $startSpace + $this->nullPosition * $boundings->width * (1 - ($startSpace + $endSpace)), $boundings->height); $end = new ezcGraphCoordinate($boundings->width * $startSpace + $this->nullPosition * $boundings->width * (1 - ($startSpace + $endSpace)), 0); break; case ezcGraph::LEFT: $start = new ezcGraphCoordinate(0, $boundings->height * $endSpace + $this->nullPosition * $boundings->height * (1 - ($startSpace + $endSpace))); $end = new ezcGraphCoordinate($boundings->width, $boundings->height * $endSpace + $this->nullPosition * $boundings->height * (1 - ($startSpace + $endSpace))); break; case ezcGraph::RIGHT: $start = new ezcGraphCoordinate($boundings->width, $boundings->height * $endSpace + $this->nullPosition * $boundings->height * (1 - ($startSpace + $endSpace))); $end = new ezcGraphCoordinate(0, $boundings->height * $endSpace + $this->nullPosition * $boundings->height * (1 - ($startSpace + $endSpace))); break; } $renderer->drawAxis($boundings, $start, $end, $this, $this->axisLabelRenderer, $innerBoundings); return $boundings; }
/** * Render the assigned data * * Will renderer all charts data in the remaining boundings after drawing * all other chart elements. The data will be rendered depending on the * settings in the dataset. * * @param ezcGraphRenderer $renderer Renderer * @param ezcGraphBoundings $boundings Remaining boundings * @return void */ protected function renderData(ezcGraphRenderer $renderer, ezcGraphBoundings $boundings, ezcGraphBoundings $innerBoundings) { // Use inner boundings for drawning chart data $boundings = $innerBoundings; $yAxisNullPosition = $this->elements['yAxis']->getCoordinate(false); // Initialize counters $nr = array(); $count = array(); foreach ($this->data as $data) { if (!isset($nr[$data->displayType->default])) { $nr[$data->displayType->default] = 0; $count[$data->displayType->default] = 0; } $nr[$data->displayType->default]++; $count[$data->displayType->default]++; } $checkedRegularSteps = false; // Display data foreach ($this->data as $datasetName => $data) { --$nr[$data->displayType->default]; // Check which axis should be used $xAxis = $data->xAxis->default ? $data->xAxis->default : $this->elements['xAxis']; $yAxis = $data->yAxis->default ? $data->yAxis->default : $this->elements['yAxis']; // Determine fill color for dataset if ($this->options->fillLines !== false) { $fillColor = clone $data->color->default; $fillColor->alpha = (int) round((255 - $fillColor->alpha) * ($this->options->fillLines / 255)); } else { $fillColor = null; } // Ensure regular steps on axis when used with bar charts and // precalculate some values use to render bar charts // // Called only once and only when bars should be rendered if ($checkedRegularSteps === false && $data->displayType->default === ezcGraph::BAR) { $steps = $xAxis->getSteps(); $stepWidth = null; foreach ($steps as $step) { if ($stepWidth === null) { $stepWidth = $step->width; } elseif ($step->width !== $stepWidth) { throw new ezcGraphUnregularStepsException(); } } $step = reset($steps); if (count($step->childs)) { // Keep this for BC reasons $barCount = ($xAxis->getMajorStepCount() + 1) * ($xAxis->getMinorStepCount() - 1); $stepWidth = 1 / $barCount; } $checkedRegularSteps = true; $width = $xAxis->axisLabelRenderer->modifyChartDataPosition($yAxis->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate(($boundings->x1 - $boundings->x0) * $stepWidth, 0)))->x; } // Draw lines for dataset $lastPoint = false; foreach ($data as $key => $value) { // Calculate point in chart $point = $xAxis->axisLabelRenderer->modifyChartDataPosition($yAxis->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate($xAxis->getCoordinate($key), $yAxis->getCoordinate($value)))); // Render depending on display type of dataset switch (true) { case $data->displayType->default === ezcGraph::LINE: $renderer->drawDataLine($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $data->color->default, $lastPoint === false ? $point : $lastPoint, $point, $nr[$data->displayType->default], $count[$data->displayType->default], $data->symbol[$key], $data->color[$key], $fillColor, $yAxisNullPosition, $data->lineThickness->default ? $data->lineThickness->default : $this->options->lineThickness); break; case $data->displayType->default === ezcGraph::BAR && $this->options->stackBars: // Check if a bar has already been stacked if (!isset($stackedValue[(int) ($point->x * 10000)][(int) $value > 0])) { $start = new ezcGraphCoordinate($point->x, $yAxisNullPosition); $stackedValue[(int) ($point->x * 10000)][(int) $value > 0] = $value; } else { $start = $xAxis->axisLabelRenderer->modifyChartDataPosition($yAxis->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate($xAxis->getCoordinate($key), $yAxis->getCoordinate($stackedValue[(int) ($point->x * 10000)][(int) $value > 0])))); $point = $xAxis->axisLabelRenderer->modifyChartDataPosition($yAxis->axisLabelRenderer->modifyChartDataPosition(new ezcGraphCoordinate($xAxis->getCoordinate($key), $yAxis->getCoordinate($stackedValue[(int) ($point->x * 10000)][(int) $value > 0] += $value)))); } // Force one symbol for each stacked bar if (!isset($stackedSymbol[(int) ($point->x * 10000)])) { $stackedSymbol[(int) ($point->x * 10000)] = $data->symbol[$key]; } // Store stacked value for next iteration $side = $point->y == 0 ? 1 : $point->y / abs($point->y); $stacked[(int) ($point->x * 10000)][$side] = $point; $renderer->drawStackedBar($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $data->color->default, $start, $point, $width, $stackedSymbol[(int) ($point->x * 10000)], $yAxisNullPosition); break; case $data->displayType->default === ezcGraph::BAR: $renderer->drawBar($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $data->color[$key], $point, $width, $nr[$data->displayType->default], $count[$data->displayType->default], $data->symbol[$key], $yAxisNullPosition); break; default: throw new ezcGraphInvalidDisplayTypeException($data->displayType->default); break; } // Render highlight string if requested if ($data->highlight[$key]) { $renderer->drawDataHighlightText($boundings, new ezcGraphContext($datasetName, $key, $data->url[$key]), $point, $yAxisNullPosition, $nr[$data->displayType->default], $count[$data->displayType->default], $this->options->highlightFont, $data->highlightValue[$key] ? $data->highlightValue[$key] : $value, $this->options->highlightSize + $this->options->highlightFont->padding * 2, $this->options->highlightLines ? $data->color[$key] : null, $this->options->highlightXOffset ? $this->options->highlightXOffset : 0, $this->options->highlightYOffset ? $this->options->highlightYOffset : 0); } // Store last point, used to connect lines in line chart. $lastPoint = $point; } } }
/** * __get * * @param mixed $propertyName * @throws ezcBasePropertyNotFoundException * If a the value for the property options is not an instance of * @return mixed * @ignore */ public function __get($propertyName) { switch ($propertyName) { case 'options': return $this->options; default: return parent::__get($propertyName); } }