Source for file AxisDraw.php
Documentation is available at AxisDraw.php
* @copyright (c) 1995-2008 by Steema Software SL. All Rights Reserved. <info@steema.com>
* @link http://www.steema.com
private static $DIFFLOAT = 0.0000001;
private static $MAXAXISTICKS = 2000;
private $drawTicksAndGrid;
private $tmpWhichDatetime; // DateTimeStep
function __get( $property ) {
$method = "get{$property}";
function __set ( $property,$value ) {
$method = "set{$property}";
return $this->$method($value);
return $this->tmpNumTicks;
private function getDepthAxisPos() {
if($this->axis->getOtherSide())
$result = $this->chart->getChartRect()->getBottom() - $this->axis->calcZPos();
$result = $this->chart->getChartRect()->getTop() + $this->axis->calcZPos();
private function drawAxisTitle() {
if (($this->axis->getTitle() != null) && $this->axis->getTitle()->getVisible() &&
(strlen($this->axis->getTitle()->getCaption()) != 0)) {
$tmp= $this->axis->getChart()->getChartRect();
if ($this->axis->isDepthAxis) {
$this->axis->drawTitle($this->axis->posTitle,$tmp->getBottom());
if ($this->axis->getHorizontal()) {
$this->axis->drawTitle($this->axis->iCenterPos, $this->axis->posTitle);
$this->axis->drawTitle($this->axis->posTitle, $this->axis->iCenterPos);
private function addTick($aPos) {
$this->ticks[$this->tmpNumTicks] = $aPos;
private function internalDrawLabel($decValue) {
$axislabels= $this->axis->getLabels();
if ($axislabels->getOnAxis() ||
(($tmp > $this->axis->iStartPos) && ($tmp < $this->axis->iEndPos))) {
if (!$this->axis->getTickOnLabelsOnly()) {
if ($axislabels->getVisible()) {
$this->drawThisLabel($tmp,$axislabels->labelValue($this->tmpValue), null);
$this->tmpWhichDatetime);
private function drawThisLabel($labelPos, $tmpSt, $labelItem) {
$old_name = TChart::$controlName;
TChart::$controlName .= 'Axis_Label_';
if ($this->axis->getTickOnLabelsOnly()) {
$this->addTick($labelPos);
$g = $c->getGraphics3D();
$axisLabels = $this->axis->getLabels();
$g->setFont(($labelItem == null) ? $axisLabels->getFont() :
$g->getBrush()->setVisible(false);
if ($this->axis->isDepthAxis) {
$g->setTextAlign($this->axis->getDepthAxisAlign());
if (($aspect->getRotation() == 360) ||
$aspect->getOrthogonal()) {
$tmpZ += ($g->getFontHeight() / 2);
if ($this->axis->getOtherSide()) {
$tmpPos = $axisLabels->position;
$tmpPos = $axisLabels->position- 2- ($this->chart->getGraphics3D()->textWidth("W") / 2);
$g->textOut($tmpPos,$this->getDepthAxisPos(),
if ($axisLabels->getAlternate()) {
$tmpPos = $axisLabels->position;
if ($this->axis->getHorizontal()) {
if ($this->axis->getOtherSide()) {
$tmpPos = $axisLabels->position -
$tmpPos = $axisLabels->position +
if ($this->axis->getOtherSide()) {
$tmpPos = $axisLabels->position +
$this->axis->maxLabelsWidth();
$tmpPos = $axisLabels->position -
$this->axis->maxLabelsWidth();
$tmpPos = $axisLabels->position;
if ($this->axis->getHorizontal()) {
$this->axis->_drawAxisLabel($labelPos,
$axisLabels->getAngle(), $tmpSt, $labelItem);
$this->axis->_drawAxisLabel($tmpPos,
$labelPos, $axisLabels->getAngle(), $tmpSt,
TChart::$controlName= $old_name;
private function intPower($numBase, $exponent) {
return pow($numBase, $exponent);
private function logBaseN($numBase, $x) {
return log($x, $numBase);
private function roundDate($aDate, $aStep) {
$tmpDateTime = new DateTime();
if ($aDate->toDouble() <= $tmpDateTime->MINVALUE) {
$year = $aDate->getYear();
$month = $aDate->getMonth();
return new $tmpDateTime($year, $month, $day);
private function doDefaultLabels() {
$this->tmpValue = MathUtils::round($this->axis->iMaximum / $this->iIncrement);
if (abs($this->axis->iRange / $this->iIncrement) < 10000) {
/* if less than 10000 labels... */
/* calculate the maximum value... */
if ($this->axis->iAxisDateTime &&
$this->axis->getLabels()->getExactDateTime() &&
$this->tmpValue = $this->roundDate(new DateTime($this->axis->iMaximum),
$this->tmpWhichDatetime)->toDouble();
if (((string) $this->axis->iMinimum==(string) $this->axis->iMaximum)
|| (!$this->axis->getLabels()->getRoundFirstLabel())) {
/* adjust the maximum value to be inside "IMinimum" and "IMaximum" */
$this->iIncrement, $this->tmpWhichDatetime);
if ($this->axis->iRangezero) {
$this->internalDrawLabel(false);
/* Maximum is equal to Minimum. Draw one label */
/* do the loop and draw labels... */
//if ((Math.abs(axis.iMaximum-axis.iMinimum)<1e-10) || (tmpValue.ToString()==(tmpValue-iIncrement).ToString()))
if ((abs($this->axis->iMaximum - $this->axis->iMinimum) <
$this->axis->iMinAxisIncrement) ||
/* fix zooming when axis Max=Min */
$this->internalDrawLabel(false);
/* draw labels until "tmpVale" is less than minimum */
$tmp = ($this->axis->iMinimum -
$this->axis->iMinAxisIncrement) /
(1.0 + $this->axis->iMinAxisIncrement);
$this->internalDrawLabel(true);
private function doDefaultLogLabels() {
if ($this->axis->iMinimum != $this->axis->iMaximum) {
if ($this->axis->iMinimum <= 0) {
if ($this->axis->iMinimum == 0) {
$this->axis->iMinimum = 0.1;
$this->axis->iMinimum = Axis::$MINAXISRANGE;
$this->tmpValue = $this->intPower($this->axis->getLogarithmicBase(),
MathUtils::round($this->logBaseN($this->axis->
$this->getLogarithmicBase(),
$this->axis->iMinimum)));
$showMinorGrid = ($this->axis->minorGrid != null) &&
($this->axis->minorGrid->getVisible());
if ($tmpValue2 >= $this->axis->iMinimum) {
$tmpValue2 = $this->intPower($this->axis->getLogarithmicBase(),
$this->getLogarithmicBase(),
$this->axis->iMinimum)) - 1);
if ($tmpValue2 < $this->axis->iMinimum) {
$this->addTick($this->axis->calcPosValue($tmpValue2));
if ($this->axis->getLogarithmicBase() > 1) {
$this->internalDrawLabel(false);
// For minor grids only...
if ($showMinorGrid && ($this->tmpValue > $this->axis->iMaximum)) {
private function doNotCustomLabels() {
if ($this->axis->getLogarithmic() && ($this->axis->getIncrement() == 0)) {
$this->doDefaultLogLabels();
$this->doDefaultLabels();
private function doCustomLabels() {
// maximum 2000 labels...
if ($this->axis->chart->getParent() != null) {
/* Add this check ?? TODO
$this->labelText = $tmpResult;
// Args : Axis, valueindex display order, label
$parent->TriggerEvent('OnGetAxisLabel', array($this->axis,$this->axis->labelIndex, $this->labelText));
if ($this->labelText != $tmpResult)
$tmpResult = $this->labelText;
$this->doNotCustomLabels();
($this->axis->iMinimum - self::$DIFFLOAT)) &&
($this->axis->iMaximum + self::$DIFFLOAT)));
$this->internalDrawLabel(false);
} while ($labelInside || ($labelIndex < 2000) || (!$r->getStop()));
private function calcFirstLastAllSeries($rect) {
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++ ) {
$s = $this->axis->iSeriesList->getSeries($t);
$s->calcFirstLastVisibleIndex();
if (($s->getFirstVisible() < $tmp->first) &&
($s->getFirstVisible() != - 1)) {
$tmp->first = $s->getFirstVisible();
if ($s->getLastVisible() > $tmp->last) {
$tmp->last = $s->getLastVisible();
private function calcAllSeries() {
if ($this->axis->iSeriesList == null) {
$this->axis->iSeriesList->clear();
for ( $t = 0; $t < $this->axis->chart->getSeriesCount(); $t++ ) {
$s = $this->axis->chart->getSeries($t);
if ($s->getActive() && $s->associatedToAxis($this->axis)) {
$this->axis->iSeriesList->internalAdd($s);
private function getAxisSeriesLabel($aIndex) {
for ( $t = 0; $t < sizeof($this->axis->iSeriesList); $t++ ) {
$tmpSeries = $this->axis->iSeriesList->getSeries($t);
if (($aIndex >= $tmpSeries->getFirstVisible()) &&
($this->aIndex <= $tmpSeries->getLastVisible())) {
// even if the series has no text labels
$result->label = $tmpSeries->getValueMarkText($aIndex);
$labels = $tmpSeries->getLabels();
$result->label = $labels[$aIndex];
if ($this->axis->chart->getParent() != null) {
$result->label = $this->axis->chart->getParent()->getAxisLabelResolver()->
if (strlen($result->label) != 0) {
if ($this->axis->getHorizontal()) {
$result->value = $tmpSeries->getXValues()->value[$aIndex];
$result->value = $tmpSeries->getYValues()->value[$aIndex];
private function depthAxisLabels() {
if ($this->axis->chart->countActiveSeries() > 0) {
$axisLabels = $this->axis->getLabels();
for ( $t = (int) $this->axis->iMinimum; $t <= $this->axis->iMaximum; $t++ ) {
$tmp = $this->axis->calcYPosValue($this->axis->iMaximum - $t - 0.5);
if (!$this->axis->getTickOnLabelsOnly()) {
if ($axisLabels->getVisible()) {
$tmpSt = $this->axis->chart->getSeriesTitleLegend($t, true);
if ($this->axis->chart->getParent() != null) {
// Args : Axis, valueindex display order, label
$this->labelText = $tmpSt;
$this->axis->chart->getParent()->TriggerEvent('OnGetAxisLabel',
array($this->axis, $t, $this->labelText));
if ($this->labelText != $tmpSt)
$tmpSt = $this->labelText;
$this->drawThisLabel($tmp, $tmpSt, null);
private function axisLabelsSeries($rect) {
/* Select all active Series that have "Labels" */
$tmpRange = $this->calcFirstLastAllSeries($rect);
if ($tmpRange->first != intval('1000000000000')) { // MAX_VALUE
$tmpLabelW = $this->axis->getHorizontal();
switch ($this->axis->getLabels()->iAngle) {
$tmpLabelW = !$tmpLabelW;
$axisLabels = $this->axis->getLabels();
for ( $t = $tmpRange->first; $t <= $tmpRange->last; $t++ ) {
$r = $this->getAxisSeriesLabel($t);
if (($tmpValue >= $this->axis->iMinimum) &&
$tmp = $this->axis->calcPosValue($tmpValue);
if (!$this->axis->getTickOnLabelsOnly()) {
if ($axisLabels->getVisible() &&
$tmpMulti = $this->axis->chart->multiLineTextWidth(
$tmpLabelSize = $tmpMulti->width;
$tmpNum = $tmpMulti->count;
$tmpLabelSize = $this->chart->getGraphics3D()->getFontHeight() * $tmpNum;
if (($axisLabels->iSeparation != 0) &&
($this->oldPosLabel != - 1)) {
$tmpLabelSize += (int) (0.02 * $tmpLabelSize *
$axisLabels->iSeparation);
if ($tmp >= $oldPosLabel) {
$this->drawThisLabel($tmp, $tmpSt, null);
$oldSizeLabel = $tmpLabelSize;
$this->drawThisLabel($tmp, $tmpSt, null);
$oldSizeLabel = $tmpLabelSize / 2;
$this->axis->iSeriesList->clear(false);
private function drawCustomLabels() {
$axisLabels = $this->axis->getLabels();
for ( $t = 0; $t < sizeof($axisLabels->getItems()); $t++ ) {
$tmpItem = $axisLabels->getItems()->getItem($t);
if ($tmpItem->getValue() >= $this->axis->getMinimum() &&
$tmpItem->getValue() <= $this->axis->getMaximum()) {
$tmp = $this->axis->calcPosValue($tmpItem->getValue());
if (!$this->axis->getTickOnLabelsOnly()) {
if ($tmpItem->getVisible()) {
$tmpSt = $tmpItem->getText();
$tmpSt = $axisLabels->labelValue($tmpItem->getValue());
$this->drawThisLabel($tmp, $tmpSt, $tmpItem);
public function draw($calcPosAxis) {
$this->axis->iAxisDateTime = $this->axis->isDateTime();
$this->axis->posAxis = $this->axis->applyPosition($this->axis->
getRectangleEdge($this->axis->chart->getChartRect()),
$this->axis->chart->getChartRect());
$this->ticks = Array(); // [self::$MAXAXISTICKS];
$axisLabels = $this->axis->getLabels();
if ($axisLabels->getItems()->count() == 0) {
$this->tmpLabelStyle = $this->axis->calcLabelStyle();
// Assign font before CalcIncrement !
$this->chart->getGraphics3D()->setFont($axisLabels->getFont());
$this->iIncrement = $this->axis->getCalcIncrement();
if ($this->axis->iAxisDateTime &&
$axisLabels->getExactDateTime() &&
($this->axis->getIncrement() != 0)) {
$this->tmpWhichDatetime = Axis::findDateTimeStep(
$this->axis->getIncrement());
while (($this->iIncrement >
($tmpDateTimeStep->STEP[$this->tmpWhichDatetime])) &&
($this->tmpWhichDatetime !=
$this->tmpWhichDatetime += 1;
if ((($this->iIncrement > 0) ||
(($this->tmpWhichDatetime >=
($this->tmpWhichDatetime <=
&& ($this->axis->iMaximum >= $this->axis->iMinimum)) {
if ($this->tmpLabelStyle == AxisLabelStyle::$VALUE) {
/*if ((axis.chart.getParent() != null) && --> doNotCustomLabels is called from doCustomLabels
checkGetAxisLabelAssigned())) {
if ($this->tmpLabelStyle == AxisLabelStyle::$MARK) {
$this->axisLabelsSeries($this->axis->chart->getChartRect());
if ($this->tmpLabelStyle == AxisLabelStyle::$TEXT) {
if ($this->axis->isDepthAxis) {
$this->depthAxisLabels();
$this->axisLabelsSeries($this->axis->chart->getChartRect());
$this->drawCustomLabels();
$this->drawTicksAndGrid->drawTicksGrid($this->ticks, $this->tmpNumTicks, $this->tmpValue);
if ($this->drawTicksAndGrid != null) {
$this->drawTicksAndGrid->setChart($chart);
* @copyright (c) 1995-2008 by Steema Software SL. All Rights Reserved. <info@steema.com>
* @link http://www.steema.com
private function getZGridPosition() {
return (int) ($this->a->getWidth3D() * $this->axis->getGrid()->getZPosition() * 0.01); // 6.0
private function drawGridLine($tmp) {
if (($tmp > $this->axis->iStartPos) && ($tmp < $this->axis->iEndPos)) {
if ($this->axis->isDepthAxis) {
$this->g->verticalLine($this->r->x, $this->r->y, $this->r->getBottom(), $tmp);
$this->g->horizontalLine($this->r->x, $this->r->getRight(), $this->r->getBottom(),
} else if ($this->axis->getHorizontal()) {
if ($this->axis->getOtherSide()) {
$this->g->verticalLine($tmp, $this->r->y, $this->r->getBottom(),
if ($this->c->getAxes()->getDrawBehind()) {
$this->g->zLine($tmp, $this->axis->posAxis, $this->getZGridPosition(),
$this->g->verticalLine($tmp, $this->r->y,
$this->r->getBottom(), $this->a->getWidth3D());
$this->g->verticalLine($tmp, $this->r->y,
$this->r->getBottom(), 0);
$this->g->verticalLine($tmp, $this->r->y + 1, $this->r->getBottom(),0);
if ($this->axis->getOtherSide()) {
$this->g->horizontalLine($this->r->x, $this->r->getRight(), $tmp, $this->a->getWidth3D());
if ($this->c->getAxes()->getDrawBehind()) {
$this->g->zLine($this->axis->posAxis, $tmp, $this->getZGridPosition(),
if (!$this->axis->hideBackGrid) {
if ($this->axis->getHorizontal()) {
$this->g->verticalLine($tmp, $this->r->getTop(), $this->r->getBottom(),
$this->g->horizontalLine($this->r->x, $this->r->getRight(), $tmp,
$this->g->horizontalLine($this->r->x + 1, $this->r->getRight(), $tmp,0);
private function drawGrids() {
$old_name= TChart::$controlName;
TChart::$controlName .= 'Axis_Grid_';
$this->g->setPen($this->axis->getGrid());
// TODO if ($this->g->getPen()->getColor()->isEmpty()) {
$this->g->getPen()->setColor(new Color(128,128,128));
for ( $t = 0; $t < $this->tmpNumTicks; $t++ ) {
if ($this->axis->getGrid()->getCentered()) {
$this->drawGridLine((int) (0.5 *
($this->tmpTicks[$t] + $this->tmpTicks[$t - 1])));
$this->drawGridLine($this->tmpTicks[$t]);
TChart::$controlName= $old_name;
private function internalDrawTick($tmp, $delta, $tmpTickLength) {
if ($this->axis->isDepthAxis) {
if ($this->axis->getOtherSide()) {
$this->g->horizontalLine($this->axis->posAxis + $delta,
$this->axis->posAxis + $delta + $tmpTickLength,
$this->getDepthAxisPos(), $tmp);
$this->g->horizontalLine($this->axis->posAxis + $delta,
$this->axis->posAxis + $delta + $tmpTickLength,
$this->getDepthAxisPos(),0);
$this->g->horizontalLine($this->axis->posAxis - $delta,
$this->axis->posAxis - $delta - $tmpTickLength,
$this->getDepthAxisPos(), $tmp);
$this->g->horizontalLine($this->axis->posAxis - $delta,
$this->axis->posAxis - $delta - $tmpTickLength,
$this->getDepthAxisPos(),0);
if ($this->axis->getOtherSide()) {
if ($this->axis->getHorizontal()) {
$this->g->verticalLine($tmp,
$this->axis->posAxis - $delta,
$this->axis->posAxis - $delta -
$tmpTickLength, $this->axis->iZPos);
$this->g->verticalLine($tmp,
$this->axis->posAxis - $delta,
$this->axis->posAxis - $delta -
$this->g->horizontalLine($this->axis->posAxis + $delta,
$this->axis->posAxis + $delta +
$tmpTickLength, $tmp, $this->axis->iZPos);
$this->g->horizontalLine($this->axis->posAxis + $delta,
$this->axis->posAxis + $delta +
$delta += $this->tmpWallSize;
if ($this->axis->getHorizontal()) {
$this->g->verticalLine($tmp,
$this->axis->posAxis + $delta,
$this->axis->posAxis + $delta +
$tmpTickLength, $this->axis->iZPos);
$this->g->verticalLine($tmp,
$this->axis->posAxis + $delta,
$this->axis->posAxis + $delta +
$this->g->horizontalLine($this->axis->posAxis - $delta,
$this->axis->posAxis - $delta -
$tmpTickLength, $tmp, $this->axis->iZPos);
$this->g->horizontalLine($this->axis->posAxis - $delta,
$this->axis->posAxis - $delta -
$tmpTickLength, $tmp, 0);
private function drawAxisLine() {
$old_name= TChart::$controlName;
TChart::$controlName .= 'Axis_';
if ($this->axis->isDepthAxis) {
if ($this->axis->getOtherSide()) {
$tmp = $this->r->getBottom() +
$this->c->getWalls()->calcWallSize($this->c->getAxes()->getBottom()) -
$tmp = $this->r->getTop() - $this->axis->iZPos;
$this->g->line($this->axis->posAxis, $tmp, $this->axis->iStartPos,
$this->axis->posAxis, $tmp, $this->axis->iEndPos);
if ($this->axis->getHorizontal()) {
if ($this->axis->getOtherSide()) {
$this->g->horizontalLine($this->axis->iStartPos,
$this->axis->iEndPos, $this->axis->posAxis,
$this->g->horizontalLine($this->axis->iStartPos -
$this->c->getWalls()->calcWallSize($this->c->getAxes()->getLeft()),
$this->axis->posAxis + $this->tmpWallSize,
$tmp = $this->axis->getOtherSide() ? $this->tmpWallSize :
$this->g->verticalLine($this->axis->posAxis + $tmp,
$this->c->getWalls()->calcWallSize($this->c->getAxes()->getBottom()),
TChart::$controlName= $old_name;
private function aProc($aPos, $isGrid) {
if (($aPos > $this->axis->iStartPos) && ($aPos < $this->axis->iEndPos)) {
$pen = $this->axis->getMinorGrid();
$this->drawGridLine($aPos);
$this->internalDrawTick($aPos, 1,
$this->axis->getMinorTicks()->length);
private function processMinorTicks($isGrid) {
$tmpInvCount = 1.0 / ($this->axis->getMinorTickCount() + 1);
if ($this->tmpNumTicks > 1) {
if (!$this->axis->getLogarithmic()) {
$tmpDelta = 1.0 * ($this->tmpTicks[1] - $this->tmpTicks[0]) *
for ( $t = 1; $t <= $this->axis->getMinorTickCount(); $t++ ) {
$this->aProc($this->tmpTicks[0] - (int) ($t * $tmpDelta),
$this->aProc($this->tmpTicks[$this->tmpNumTicks - 1] +
(int) ($t * $tmpDelta), $isGrid);
for ( $t = 1; $t <= $this->tmpNumTicks - 1; $t++ ) {
if ($this->axis->getLogarithmic()) {
$tmpValue = $this->axis->calcPosPoint($this->tmpTicks[$t - 1]);
$tmpDelta = (($tmpValue *
$this->axis->getLogarithmicBase()) -
$tmpValue) * $tmpInvCount;
for ( $tt = 1; $tt < $this->axis->getMinorTickCount(); $tt++ ) {
if ($tmpValue <= $this->axis->iMaximum) {
$this->aProc($this->axis->calcPosValue($tmpValue), $isGrid);
($this->tmpTicks[$t] - $this->tmpTicks[$t - 1]) *
for ( $tt = 1; $tt <= $this->axis->getMinorTickCount(); $tt++ ) {
$this->aProc($this->tmpTicks[$t] -
(int) ($tt * $tmpDelta), $isGrid);
private function processTicks($aPen, $aOffset, $aLength) {
if ($aPen->getVisible() && ($aLength != 0)) {
$old_name= TChart::$controlName;
TChart::$controlName .= 'Axis_Ticks_';
for ( $t = 0; $t < $this->tmpNumTicks; $t++ ) {
$this->internalDrawTick($this->tmpTicks[$t], $aOffset,
TChart::$controlName= $old_name;
private function processMinor($aPen, $isGrid) {
if (($this->tmpNumTicks > 0) && $aPen->getVisible()) {
$this->processMinorTicks($isGrid);
public function drawTicksGrid($tempTicks, $tempNumTicks, $tempValue) {
$this->c = $this->axis->chart;
$this->g = $this->c->getGraphics3D();
$this->a = $this->c->getAspect();
$this->is3D = $this->a->getView3D();
$this->tmpTicks = $tempTicks;
$this->tmpNumTicks = $tempNumTicks;
$this->r = $this->c->getChartRect();
$this->g->getBrush()->setVisible(false);
$this->tmpWallSize = $this->c->getWalls()->calcWallSize($this->axis);
if ($this->axis->getAxisPen()->getVisible()) {
$this->g->setPen($this->axis->getAxisPen());
$this->processTicks($this->axis->getTicks(), 1, $this->axis->getTicks()->length);
if ($this->axis->getGrid()->getVisible()) {
$this->processTicks($this->axis->getTicksInner(), - 1, - $this->axis->getTicksInner()->length);
$this->processMinor($this->axis->getMinorTicks(), false);
if ($this->axis->getMinorGrid() != null) {
$this->processMinor($this->axis->getMinorGrid(), true);
public function IntRange($first= 0, $last= 0) {
|