/**
  * 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);
     }
 }
Example #2
0
 /**
  * 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, ezcGraphBoundings $innerBoundings = null)
 {
     // receive rendering parameters from axis
     $steps = $axis->getSteps();
     $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();
     // Get axis space
     $gridBoundings = null;
     list($xSpace, $ySpace) = $this->getAxisSpace($renderer, $boundings, $axis, $innerBoundings, $gridBoundings);
     // Determine optimal angle if none specified
     $this->determineAngle($steps, $xSpace, $ySpace, $axisBoundings);
     $degTextAngle = $this->determineTextOffset($axis, $steps);
     $labelLength = $this->calculateLabelLength($start, $end, $xSpace, $ySpace, $axisBoundings);
     // 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
         $labelSize = $this->calculateLabelSize($steps, $nr, $step, $xSpace, $ySpace, $axisBoundings);
         $lengthReducement = min(abs(tan(deg2rad($this->angle)) * ($labelSize / 2)), abs($labelLength / 2));
         $this->renderLabelText($renderer, $axis, $position, $step->label, $degTextAngle, $labelLength, $labelSize, $lengthReducement);
         // 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);
     }
 }
Example #3
0
 /**
  * Returns the angle between two vectors in radian
  * 
  * @param ezcGraphCoordinate $vector 
  * @return float
  */
 public function angle(ezcGraphCoordinate $vector)
 {
     if (!$vector instanceof ezcGraphVector) {
         // Ensure beeing a vector for calling length()
         $vector = ezcGraphVector::fromCoordinate($vector);
     }
     $factor = $this->length() * $vector->length();
     if ($factor == 0) {
         return false;
     } else {
         return acos($this->mul($vector) / $factor);
     }
 }
Example #4
0
 /**
  * Draw axis
  *
  * Draws an axis form the provided start point to the end point. A specific 
  * angle of the axis is not required.
  *
  * For the labeleing of the axis a sorted array with major steps and an 
  * array with minor steps is expected, which are build like this:
  *  array(
  *      array(
  *          'position' => (float),
  *          'label' => (string),
  *      )
  *  )
  * where the label is optional.
  *
  * The label renderer class defines how the labels are rendered. For more
  * documentation on this topic have a look at the basic label renderer 
  * class.
  *
  * Additionally it can be specified if a major and minor grid are rendered 
  * by defining a color for them. The axis label is used to add a caption 
  * for the axis.
  * 
  * @param ezcGraphBoundings $boundings Boundings of axis
  * @param ezcGraphCoordinate $start Start point of axis
  * @param ezcGraphCoordinate $end Endpoint of axis
  * @param ezcGraphChartElementAxis $axis Axis to render
  * @param ezcGraphAxisLabelRenderer $labelClass Used label renderer
  * @return void
  */
 public function drawAxis(ezcGraphBoundings $boundings, ezcGraphCoordinate $start, ezcGraphCoordinate $end, ezcGraphChartElementAxis $axis, ezcGraphAxisLabelRenderer $labelClass = null)
 {
     // Calculate used space for three dimensional effects
     if ($this->depth === false) {
         $this->depth = min(($boundings->x1 - $boundings->x0) * $this->options->depth, ($boundings->y1 - $boundings->y0) * $this->options->depth);
         $this->xDepthFactor = 1 - $this->depth / ($boundings->x1 - $boundings->x0);
         $this->yDepthFactor = 1 - $this->depth / ($boundings->y1 - $boundings->y0);
         $this->dataBoundings = clone $boundings;
     }
     // Clone boundings to not be affected by internal mofifications
     $boundings = clone $boundings;
     switch ($axis->position) {
         case ezcGraph::TOP:
         case ezcGraph::BOTTOM:
             $this->xAxisSpace = ($this->dataBoundings->x1 - $this->dataBoundings->x0) * $axis->axisSpace;
             break;
         case ezcGraph::LEFT:
         case ezcGraph::RIGHT:
             $this->yAxisSpace = ($this->dataBoundings->y1 - $this->dataBoundings->y0) * $axis->axisSpace;
             break;
     }
     // Determine normalized direction
     $direction = new ezcGraphVector($start->x - $end->x, $start->y - $end->y);
     $direction->unify();
     $start->x += $boundings->x0;
     $start->y += $boundings->y0;
     $end->x += $boundings->x0;
     $end->y += $boundings->y0;
     // Shorten drawn axis, if requested.
     if ($this->options->shortAxis === true && ($axis->position === ezcGraph::TOP || $axis->position === ezcGraph::BOTTOM)) {
         $axisStart = clone $start;
         $axisEnd = clone $end;
         $axisStart->y += $boundings->height * $axis->axisSpace * ($axis->position === ezcGraph::TOP ? 1 : -1);
         $axisEnd->y -= $boundings->height * $axis->axisSpace * ($axis->position === ezcGraph::TOP ? 1 : -1);
     } elseif ($this->options->shortAxis === true && ($axis->position === ezcGraph::LEFT || $axis->position === ezcGraph::RIGHT)) {
         $axisStart = clone $start;
         $axisEnd = clone $end;
         $axisStart->x += $boundings->width * $axis->axisSpace * ($axis->position === ezcGraph::LEFT ? 1 : -1);
         $axisEnd->x -= $boundings->width * $axis->axisSpace * ($axis->position === ezcGraph::LEFT ? 1 : -1);
     } else {
         $axisStart = $start;
         $axisEnd = $end;
     }
     $axisPolygonCoordinates = array($this->get3dCoordinate($axisStart, true), $this->get3dCoordinate($axisEnd, true), $this->get3dCoordinate($axisEnd, false), $this->get3dCoordinate($axisStart, false));
     // Draw axis
     if ($this->options->fillAxis > 0 && $this->options->fillAxis < 1) {
         $this->driver->drawPolygon($axisPolygonCoordinates, $axis->border->transparent($this->options->fillAxis), true);
     } else {
         $this->driver->drawPolygon($axisPolygonCoordinates, $axis->border, !(bool) $this->options->fillAxis);
     }
     // Draw axis lines - scedule some for later to be drawn in front of
     // the data
     $this->driver->drawLine($axisPolygonCoordinates[0], $axisPolygonCoordinates[1], $axis->border, 1);
     $this->frontLines[] = array($axisPolygonCoordinates[1], $axisPolygonCoordinates[2], $axis->border, 1);
     $this->frontLines[] = array($axisPolygonCoordinates[2], $axisPolygonCoordinates[3], $axis->border, 1);
     $this->frontLines[] = array($axisPolygonCoordinates[3], $axisPolygonCoordinates[0], $axis->border, 1);
     // Draw small arrowhead
     $this->drawAxisArrowHead($axisPolygonCoordinates[1], $direction, max($axis->minArrowHeadSize, min($axis->maxArrowHeadSize, abs(ceil(($end->x - $start->x + ($end->y - $start->y)) * $axis->axisSpace / 4)))), $axis->border);
     // Draw axis label
     if ($axis->label !== false) {
         $width = $this->dataBoundings->x1 - $this->dataBoundings->x0;
         switch ($axis->position) {
             case ezcGraph::TOP:
                 $this->driver->drawTextBox($axis->label, new ezcGraphCoordinate($axisPolygonCoordinates[2]->x + $axis->labelMargin - $width * (1 - $axis->axisSpace * 2), $axisPolygonCoordinates[2]->y - $axis->labelMargin - $axis->labelSize), $width * (1 - $axis->axisSpace * 2) - $axis->labelMargin, $axis->labelSize, ezcGraph::TOP | ezcGraph::RIGHT);
                 break;
             case ezcGraph::BOTTOM:
                 $this->driver->drawTextBox($axis->label, new ezcGraphCoordinate($axisPolygonCoordinates[1]->x + $axis->labelMargin, $axisPolygonCoordinates[1]->y + $axis->labelMargin), $width * (1 - $axis->axisSpace * 2) - $axis->labelMargin, $axis->labelSize, ezcGraph::TOP | ezcGraph::LEFT);
                 break;
             case ezcGraph::LEFT:
                 $this->driver->drawTextBox($axis->label, new ezcGraphCoordinate($axisPolygonCoordinates[1]->x - $width, $axisPolygonCoordinates[1]->y - $axis->labelSize - $axis->labelMargin), $width - $axis->labelMargin, $axis->labelSize, ezcGraph::BOTTOM | ezcGraph::RIGHT);
                 break;
             case ezcGraph::RIGHT:
                 $this->driver->drawTextBox($axis->label, new ezcGraphCoordinate($axisPolygonCoordinates[1]->x, $axisPolygonCoordinates[1]->y - $axis->labelSize - $axis->labelMargin), $width - $axis->labelMargin, $axis->labelSize, ezcGraph::BOTTOM | ezcGraph::LEFT);
                 break;
         }
     }
     // Collect axis labels and draw, when all axisSpaces are collected
     $this->axisLabels[] = array('object' => $labelClass, 'boundings' => $boundings, 'start' => clone $start, 'end' => clone $end, 'axis' => $axis);
     if ($this->xAxisSpace && $this->yAxisSpace) {
         foreach ($this->axisLabels as $axisLabel) {
             // If font should not be synchronized, use font configuration from
             // each axis
             if ($this->options->syncAxisFonts === false) {
                 $this->driver->options->font = $axisLabel['axis']->font;
             }
             switch ($axisLabel['axis']->position) {
                 case ezcGraph::RIGHT:
                 case ezcGraph::LEFT:
                     $axisLabel['start']->x += $this->xAxisSpace * ($axisLabel['start'] > $axisLabel['end'] ? -1 : 1);
                     $axisLabel['end']->x -= $this->xAxisSpace * ($axisLabel['start'] > $axisLabel['end'] ? -1 : 1);
                     break;
                 case ezcGraph::TOP:
                 case ezcGraph::BOTTOM:
                     $axisLabel['start']->y += $this->yAxisSpace * ($axisLabel['start'] > $axisLabel['end'] ? -1 : 1);
                     $axisLabel['end']->y -= $this->yAxisSpace * ($axisLabel['start'] > $axisLabel['end'] ? -1 : 1);
                     break;
             }
             $axisLabel['object']->renderLabels($this, $axisLabel['boundings'], $axisLabel['start'], $axisLabel['end'], $axisLabel['axis']);
         }
     }
 }
 /**
  * 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, ezcGraphBoundings $innerBoundings = null)
 {
     // receive rendering parameters from axis
     $steps = $axis->getSteps();
     $axisBoundings = new ezcGraphBoundings($start->x, $start->y, $end->x, $end->y);
     // Determine normalized axis direction
     $direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y);
     $direction->unify();
     // Get axis space
     $gridBoundings = null;
     list($xSpace, $ySpace) = $this->getAxisSpace($renderer, $boundings, $axis, $innerBoundings, $gridBoundings);
     // Draw steps and grid
     foreach ($steps as $nr => $step) {
         $position = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $step->position, $start->y + ($end->y - $start->y) * $step->position);
         $stepSize = new ezcGraphCoordinate($axisBoundings->width * $step->width, $axisBoundings->height * $step->width);
         if (!$step->isZero) {
             // major grid
             if ($axis->majorGrid) {
                 $this->drawGrid($renderer, $gridBoundings, $position, $stepSize, $axis->majorGrid);
             }
             // major step
             $this->drawStep($renderer, $position, $direction, $axis->position, $this->majorStepSize, $axis->border);
         }
         // draw label
         if ($this->showLabels && ($this->showZeroValue || !$step->isZero)) {
             // Calculate label boundings
             if (abs($direction->x) > abs($direction->y)) {
                 // Horizontal labels
                 switch (true) {
                     case $nr === 0:
                         // First label
                         $labelSize = min($xSpace * 2, $step->width * $axisBoundings->width);
                         break;
                     case $step->isLast:
                         // Last label
                         $labelSize = min($xSpace * 2, $steps[$nr - 1]->width * $axisBoundings->width);
                         break;
                     default:
                         $labelSize = min($step->width * $axisBoundings->width, $steps[$nr - 1]->width * $axisBoundings->width);
                         break;
                 }
                 $labelBoundings = new ezcGraphBoundings($position->x - $labelSize / 2 + $this->labelPadding, $position->y + $this->labelPadding, $position->x + $labelSize / 2 - $this->labelPadding, $position->y + $ySpace - $this->labelPadding);
                 $alignement = ezcGraph::CENTER | ezcGraph::TOP;
             } else {
                 // Vertical labels
                 switch (true) {
                     case $nr === 0:
                         // First label
                         $labelSize = min($ySpace * 2, $step->width * $axisBoundings->height);
                         break;
                     case $step->isLast:
                         // Last label
                         $labelSize = min($ySpace * 2, $steps[$nr - 1]->width * $axisBoundings->height);
                         break;
                     default:
                         $labelSize = min($step->width * $axisBoundings->height, $steps[$nr - 1]->width * $axisBoundings->height);
                         break;
                 }
                 $labelBoundings = new ezcGraphBoundings($position->x - $xSpace + $this->labelPadding, $position->y - $labelSize / 2 + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $labelSize / 2 - $this->labelPadding);
                 $alignement = ezcGraph::MIDDLE | ezcGraph::RIGHT;
             }
             $renderer->drawText($labelBoundings, $step->label, $alignement);
         }
         // Iterate over minor steps
         if (!$step->isLast) {
             foreach ($step->childs as $minorStep) {
                 $minorStepPosition = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $minorStep->position, $start->y + ($end->y - $start->y) * $minorStep->position);
                 $minorStepSize = new ezcGraphCoordinate($axisBoundings->width * $minorStep->width, $axisBoundings->height * $minorStep->width);
                 if ($axis->minorGrid) {
                     $this->drawGrid($renderer, $gridBoundings, $minorStepPosition, $minorStepSize, $axis->minorGrid);
                 }
                 // major step
                 $this->drawStep($renderer, $minorStepPosition, $direction, $axis->position, $this->minorStepSize, $axis->border);
             }
         }
     }
 }
 /**
  * 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, ezcGraphBoundings $innerBoundings = null)
 {
     // receive rendering parameters from axis
     $steps = $axis->getSteps();
     $axisBoundings = new ezcGraphBoundings($start->x, $start->y, $end->x, $end->y);
     // Determine normalized axis direction
     $direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y);
     $direction->unify();
     // Get axis space
     $gridBoundings = null;
     list($xSpace, $ySpace) = $this->getAxisSpace($renderer, $boundings, $axis, $innerBoundings, $gridBoundings);
     // Draw steps and grid
     foreach ($steps as $nr => $step) {
         $position = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $step->position, $start->y + ($end->y - $start->y) * $step->position);
         $stepSize = new ezcGraphCoordinate($axisBoundings->width * $step->width, $axisBoundings->height * $step->width);
         if (!$step->isZero) {
             // major grid
             if ($axis->majorGrid) {
                 $this->drawGrid($renderer, $gridBoundings, $position, $stepSize, $axis->majorGrid);
             }
             // major step
             $this->drawStep($renderer, $position, $direction, $axis->position, $this->majorStepSize, $axis->border);
         }
         if ($this->showLabels) {
             switch ($axis->position) {
                 case ezcGraph::RIGHT:
                 case ezcGraph::LEFT:
                     $labelWidth = $axisBoundings->width * $steps[$nr - $step->isLast]->width / ($this->showLastValue + 1);
                     $labelHeight = $ySpace;
                     if ($this->renderLastOutside === true && $step->isLast === true) {
                         $labelWidth = ($boundings->width - $axisBoundings->width) / 2;
                     }
                     break;
                 case ezcGraph::BOTTOM:
                 case ezcGraph::TOP:
                     $labelWidth = $xSpace;
                     $labelHeight = $axisBoundings->height * $steps[$nr - $step->isLast]->width / ($this->showLastValue + 1);
                     if ($this->renderLastOutside === true && $step->isLast === true) {
                         $labelHeight = ($boundings->height - $axisBoundings->height) / 2;
                     }
                     break;
             }
             $showLabel = true;
             switch (true) {
                 case !$this->showLastValue && $step->isLast:
                     // Skip last step if showLastValue is false
                     $showLabel = false;
                     break;
                     // Draw label at top left of step
                 // Draw label at top left of step
                 case $axis->position === ezcGraph::BOTTOM && !$step->isLast || $axis->position === ezcGraph::BOTTOM && $step->isLast && $this->renderLastOutside || $axis->position === ezcGraph::TOP && $step->isLast && !$this->renderLastOutside:
                     $labelBoundings = new ezcGraphBoundings($position->x - $labelWidth + $this->labelPadding, $position->y - $labelHeight + $this->labelPadding, $position->x - $this->labelPadding, $position->y - $this->labelPadding);
                     $alignement = ezcGraph::RIGHT | ezcGraph::BOTTOM;
                     break;
                     // Draw label at bottom right of step
                 // Draw label at bottom right of step
                 case $axis->position === ezcGraph::LEFT && !$step->isLast || $axis->position === ezcGraph::LEFT && $step->isLast && $this->renderLastOutside || $axis->position === ezcGraph::RIGHT && $step->isLast && !$this->renderLastOutside:
                     $labelBoundings = new ezcGraphBoundings($position->x + $this->labelPadding, $position->y + $this->labelPadding, $position->x + $labelWidth - $this->labelPadding, $position->y + $labelHeight - $this->labelPadding);
                     $alignement = ezcGraph::LEFT | ezcGraph::TOP;
                     break;
                     // Draw label at bottom left of step
                 // Draw label at bottom left of step
                 case $axis->position === ezcGraph::TOP && !$step->isLast || $axis->position === ezcGraph::TOP && $step->isLast && $this->renderLastOutside || $axis->position === ezcGraph::RIGHT && !$step->isLast || $axis->position === ezcGraph::RIGHT && $step->isLast && $this->renderLastOutside || $axis->position === ezcGraph::BOTTOM && $step->isLast && !$this->renderLastOutside || $axis->position === ezcGraph::LEFT && $step->isLast && !$this->renderLastOutside:
                     $labelBoundings = new ezcGraphBoundings($position->x - $labelWidth + $this->labelPadding, $position->y + $this->labelPadding, $position->x - $this->labelPadding, $position->y + $labelHeight - $this->labelPadding);
                     $alignement = ezcGraph::RIGHT | ezcGraph::TOP;
                     break;
             }
             if ($showLabel) {
                 $renderer->drawText($labelBoundings, $step->label, $alignement);
             }
         }
         if (!$step->isLast) {
             // Iterate over minor steps
             foreach ($step->childs as $minorStep) {
                 $minorStepPosition = new ezcGraphCoordinate($start->x + ($end->x - $start->x) * $minorStep->position, $start->y + ($end->y - $start->y) * $minorStep->position);
                 $minorStepSize = new ezcGraphCoordinate($axisBoundings->width * $minorStep->width, $axisBoundings->height * $minorStep->width);
                 if ($axis->minorGrid) {
                     $this->drawGrid($renderer, $gridBoundings, $minorStepPosition, $minorStepSize, $axis->minorGrid);
                 }
                 // major step
                 $this->drawStep($renderer, $minorStepPosition, $direction, $axis->position, $this->minorStepSize, $axis->border);
             }
         }
     }
 }
Example #7
0
 /**
  * Draw all left axis labels
  * 
  * @return void
  */
 protected function drawAxisLabels()
 {
     foreach ($this->axisLabels as $nr => $axisLabel) {
         // If font should not be synchronized, use font configuration from
         // each axis
         if ($this->options->syncAxisFonts === false) {
             $this->driver->options->font = $axisLabel['axis']->font;
         }
         $start = $axisLabel['start'];
         $end = $axisLabel['end'];
         $direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y);
         $direction->unify();
         // Convert elipse to circle for correct angle calculation
         $direction->y *= $this->xAxisSpace / $this->yAxisSpace;
         $angle = $direction->angle(new ezcGraphVector(0, 1));
         $movement = new ezcGraphVector(sin($angle) * $this->xAxisSpace * ($direction->x < 0 ? -1 : 1), cos($angle) * $this->yAxisSpace);
         $start->x += $movement->x;
         $start->y += $movement->y;
         $end->x -= $movement->x;
         $end->y -= $movement->y;
         $axisLabel['object']->renderLabels($this, $axisLabel['boundings'], $start, $end, $axisLabel['axis']);
         // Prevent from redrawing axis on more then 2 axis.
         unset($this->axisLabels[$nr]);
     }
 }
Example #8
0
 /**
  * Reduce the size of an ellipse
  *
  * The method returns a the edgepoints and angles for an ellipse where all 
  * borders are moved to the inner side of the ellipse by the give $size 
  * value.
  *
  * The method returns an 
  * array (
  *      'center' => (ezcGraphCoordinate) New center point,
  *      'start' => (ezcGraphCoordinate) New outer start point,
  *      'end' => (ezcGraphCoordinate) New outer end point,
  * )
  * 
  * @param ezcGraphCoordinate $center 
  * @param float $width
  * @param float $height
  * @param float $startAngle 
  * @param float $endAngle 
  * @param float $size 
  * @throws ezcGraphReducementFailedException
  * @return array
  */
 protected function reduceEllipseSize(ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, $size)
 {
     $oldStartPoint = new ezcGraphVector($width * cos(deg2rad($startAngle)) / 2, $height * sin(deg2rad($startAngle)) / 2);
     $oldEndPoint = new ezcGraphVector($width * cos(deg2rad($endAngle)) / 2, $height * sin(deg2rad($endAngle)) / 2);
     // We always need radian values..
     $degAngle = abs($endAngle - $startAngle);
     $startAngle = deg2rad($startAngle);
     $endAngle = deg2rad($endAngle);
     // Calculate normalized vectors for the lines spanning the ellipse
     $unifiedStartVector = ezcGraphVector::fromCoordinate($oldStartPoint)->unify();
     $unifiedEndVector = ezcGraphVector::fromCoordinate($oldEndPoint)->unify();
     $startVector = ezcGraphVector::fromCoordinate($oldStartPoint);
     $endVector = ezcGraphVector::fromCoordinate($oldEndPoint);
     $oldStartPoint->add($center);
     $oldEndPoint->add($center);
     // Use orthogonal vectors of normalized ellipse spanning vectors to
     $v = clone $unifiedStartVector;
     $v->rotateClockwise()->scalar($size);
     // calculate new center point
     // center + v + size / tan( angle / 2 ) * startVector
     $centerMovement = clone $unifiedStartVector;
     $newCenter = $v->add($centerMovement->scalar($size / tan(($endAngle - $startAngle) / 2)))->add($center);
     // Test if center is still inside the ellipse, otherwise the sector
     // was to small to be reduced
     $innerBoundingBoxSize = 0.7 * min($width, $height);
     if ($newCenter->x < $center->x + $innerBoundingBoxSize && $newCenter->x > $center->x - $innerBoundingBoxSize && $newCenter->y < $center->y + $innerBoundingBoxSize && $newCenter->y > $center->y - $innerBoundingBoxSize) {
         // Point is in inner bounding box -> everything is OK
     } elseif ($newCenter->x < $center->x - $width || $newCenter->x > $center->x + $width || $newCenter->y < $center->y - $height || $newCenter->y > $center->y + $height) {
         // Quick outer boundings check
         if ($degAngle > 180) {
             // Use old center for very big angles
             $newCenter = clone $center;
         } else {
             // Do not draw for very small angles
             throw new ezcGraphReducementFailedException();
         }
     } else {
         // Perform exact check
         $distance = new ezcGraphVector($newCenter->x - $center->x, $newCenter->y - $center->y);
         // Convert elipse to circle for correct angle calculation
         $direction = clone $distance;
         $direction->y *= $width / $height;
         $angle = $direction->angle(new ezcGraphVector(0, 1));
         $outerPoint = new ezcGraphVector(sin($angle) * $width / 2, cos($angle) * $height / 2);
         // Point is not in ellipse any more
         if (abs($distance->x) > abs($outerPoint->x)) {
             if ($degAngle > 180) {
                 // Use old center for very big angles
                 $newCenter = clone $center;
             } else {
                 // Do not draw for very small angles
                 throw new ezcGraphReducementFailedException();
             }
         }
     }
     // Use start spanning vector and its orthogonal vector to calculate
     // new start point
     $newStartPoint = clone $oldStartPoint;
     // Create tangent vector from tangent angle
     // Ellipse tangent factor
     $ellipseTangentFactor = sqrt(pow($height, 2) * pow(cos($startAngle), 2) + pow($width, 2) * pow(sin($startAngle), 2));
     $ellipseTangentVector = new ezcGraphVector($width * -sin($startAngle) / $ellipseTangentFactor, $height * cos($startAngle) / $ellipseTangentFactor);
     // Reverse spanning vector
     $innerVector = clone $unifiedStartVector;
     $innerVector->scalar($size)->scalar(-1);
     $newStartPoint->add($innerVector)->add($ellipseTangentVector->scalar($size));
     $newStartVector = clone $startVector;
     $newStartVector->add($ellipseTangentVector);
     // Use end spanning vector and its orthogonal vector to calculate
     // new end point
     $newEndPoint = clone $oldEndPoint;
     // Create tangent vector from tangent angle
     // Ellipse tangent factor
     $ellipseTangentFactor = sqrt(pow($height, 2) * pow(cos($endAngle), 2) + pow($width, 2) * pow(sin($endAngle), 2));
     $ellipseTangentVector = new ezcGraphVector($width * -sin($endAngle) / $ellipseTangentFactor, $height * cos($endAngle) / $ellipseTangentFactor);
     // Reverse spanning vector
     $innerVector = clone $unifiedEndVector;
     $innerVector->scalar($size)->scalar(-1);
     $newEndPoint->add($innerVector)->add($ellipseTangentVector->scalar($size)->scalar(-1));
     $newEndVector = clone $endVector;
     $newEndVector->add($ellipseTangentVector);
     return array('center' => $newCenter, 'start' => $newStartPoint, 'end' => $newEndPoint, 'startAngle' => rad2deg($startAngle + $startVector->angle($newStartVector)), 'endAngle' => rad2deg($endAngle - $endVector->angle($newEndVector)));
 }
Example #9
0
 /**
  * Draws a sector of cirlce
  * 
  * @param ezcGraphCoordinate $center Center of circle
  * @param mixed $width Width
  * @param mixed $height Height
  * @param mixed $startAngle Start angle of circle sector
  * @param mixed $endAngle End angle of circle sector
  * @param ezcGraphColor $color Color
  * @param mixed $filled Filled
  * @return void
  */
 public function drawCircleSector(ezcGraphCoordinate $center, $width, $height, $startAngle, $endAngle, ezcGraphColor $color, $filled = true)
 {
     $image = $this->getImage();
     $drawColor = $this->allocate($color);
     // Normalize angles
     if ($startAngle > $endAngle) {
         $tmp = $startAngle;
         $startAngle = $endAngle;
         $endAngle = $tmp;
     }
     if ($endAngle - $startAngle > 359.99999) {
         return $this->drawCircle($center, $width, $height, $color, $filled);
     }
     // Because of bug #45552 in PHPs ext/GD we check for a minimal distance
     // on the outer border of the circle sector, and skip the drawing if
     // the distance is lower then 1.
     //
     // See also: http://bugs.php.net/45552
     $startPoint = new ezcGraphVector($center->x + cos(deg2rad($startAngle)) * $width / 2, $center->y + sin(deg2rad($startAngle)) * $height / 2);
     if ($startPoint->sub(new ezcGraphVector($center->x + cos(deg2rad($endAngle)) * $width / 2, $center->y + sin(deg2rad($endAngle)) * $height / 2))->length() < 1) {
         // Skip this circle sector
         return array();
     }
     if ($filled) {
         imagefilledarc($image, $this->supersample($center->x), $this->supersample($center->y), $this->supersample($width), $this->supersample($height), $startAngle, $endAngle, $drawColor, IMG_ARC_PIE);
     } else {
         imagefilledarc($image, $this->supersample($center->x), $this->supersample($center->y), $this->supersample($width), $this->supersample($height), $startAngle, $endAngle, $drawColor, IMG_ARC_PIE | IMG_ARC_NOFILL | IMG_ARC_EDGED);
     }
     // Create polygon array to return
     $polygonArray = array($center);
     for ($angle = $startAngle; $angle < $endAngle; $angle += $this->options->imageMapResolution) {
         $polygonArray[] = new ezcGraphCoordinate($center->x + cos(deg2rad($angle)) * $width / 2, $center->y + sin(deg2rad($angle)) * $height / 2);
     }
     $polygonArray[] = new ezcGraphCoordinate($center->x + cos(deg2rad($endAngle)) * $width / 2, $center->y + sin(deg2rad($endAngle)) * $height / 2);
     return $polygonArray;
 }
 /**
  * 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);
 }
Example #12
0
 public function testVectorTransform()
 {
     $vector = new ezcGraphVector(0, 0);
     $result = $vector->transform(new ezcGraphRotation(-90, new ezcGraphCoordinate(15, 15)));
     $this->assertEquals($vector, new ezcGraphVector(0, 30), 'Vector transformation does not have the expected result', 0.0001);
     $this->assertEquals($result, $vector, 'Result should be the vector itself');
 }
Example #13
0
 /**
  * Draw all left axis labels
  * 
  * @return void
  */
 protected function drawAxisLabels()
 {
     foreach ($this->axisLabels as $nr => $axisLabel) {
         $start = $axisLabel['start'];
         $end = $axisLabel['end'];
         $direction = new ezcGraphVector($end->x - $start->x, $end->y - $start->y);
         $direction->unify();
         // Convert elipse to circle for correct angle calculation
         $direction->y *= $this->xAxisSpace / $this->yAxisSpace;
         $angle = $direction->angle(new ezcGraphVector(0, 1));
         $movement = new ezcGraphVector(sin($angle) * $this->xAxisSpace * ($direction->x < 0 ? -1 : 1), cos($angle) * $this->yAxisSpace);
         $start->x += $movement->x;
         $start->y += $movement->y;
         $end->x -= $movement->x;
         $end->y -= $movement->y;
         $axisLabel['object']->renderLabels($this, $axisLabel['boundings'], $start, $end, $axisLabel['axis']);
         // Prevent from redrawing axis on more then 2 axis.
         unset($this->axisLabels[$nr]);
     }
 }