HuasoFoundries/jpgraph

View on GitHub
src/graph/RadarGraph.php

Summary

Maintainability
D
1 day
Test Coverage
<?php

/**
 * JPGraph v4.0.3
 */

namespace Amenadiel\JpGraph\Graph;

use Amenadiel\JpGraph\Image;
use Amenadiel\JpGraph\Plot;
use Amenadiel\JpGraph\Text;
use Amenadiel\JpGraph\Util;

/**
 * @class RadarGraph
 * // Description: Main container for a radar graph
 */
class RadarGraph extends Graph
{
    public $grid;
    public $axis;
    private $posx;
    private $posy;
    private $len;
    private $axis_title;

    public function __construct($width = 300, $height = 200, $cachedName = '', $timeout = 0, $inline = 1)
    {
        parent::__construct($width, $height, $cachedName, $timeout, $inline);
        $this->posx = $width / 2;
        $this->posy = $height / 2;
        $this->len  = min($width, $height) * 0.35;
        $this->SetColor([255, 255, 255]);
        $this->SetTickDensity(TICKD_NORMAL);
        $this->SetScale('lin');
        $this->SetGridDepth(DEPTH_FRONT);
    }

    public function HideTickMarks($aFlag = true)
    {
        $this->axis->scale->ticks->SupressTickMarks($aFlag);
    }

    public function ShowMinorTickmarks($aFlag = true)
    {
        $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
    }

    public function SetScale($axtype, $ymin = 1, $ymax = 1, $dummy1 = null, $dumy2 = null)
    {
        if ($axtype != 'lin' && $axtype != 'log') {
            Util\JpGraphError::RaiseL(18003, $axtype);
            //("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\"");
        }
        if ($axtype == 'lin') {
            $this->yscale        = new LinearScale($ymin, $ymax);
            $this->yscale->ticks = new RadarLinearTicks();
            $this->yscale->ticks->SupressMinorTickMarks();
        } elseif ($axtype == 'log') {
            $this->yscale        = new LogScale($ymin, $ymax);
            $this->yscale->ticks = new RadarLogTicks();
        }

        $this->axis = new RadarAxis($this->img, $this->yscale);
        $this->grid = new RadarGrid();
    }

    public function SetSize($aSize)
    {
        if ($aSize < 0.1 || $aSize > 1) {
            Util\JpGraphError::RaiseL(18004, $aSize);
            //("Radar Plot size must be between 0.1 and 1. (Your value=$s)");
        }
        $this->len = min($this->img->width, $this->img->height) * $aSize / 2;
    }

    public function SetPlotSize($aSize)
    {
        $this->SetSize($aSize);
    }

    public function SetTickDensity($densy = TICKD_NORMAL, $dummy1 = null)
    {
        $this->ytick_factor = 25;
        switch ($densy) {
            case TICKD_DENSE:
                $this->ytick_factor = 12;

                break;
            case TICKD_NORMAL:
                $this->ytick_factor = 25;

                break;
            case TICKD_SPARSE:
                $this->ytick_factor = 40;

                break;
            case TICKD_VERYSPARSE:
                $this->ytick_factor = 70;

                break;
            default:
                Util\JpGraphError::RaiseL(18005, $densy);
                //("RadarPlot Unsupported Tick density: $densy");
        }
    }

    public function SetPos($px, $py = 0.5)
    {
        $this->SetCenter($px, $py);
    }

    public function SetCenter($px, $py = 0.5)
    {
        if ($px >= 0 && $px <= 1) {
            $this->posx = $this->img->width * $px;
        } else {
            $this->posx = $px;
        }
        if ($py >= 0 && $py <= 1) {
            $this->posy = $this->img->height * $py;
        } else {
            $this->posy = $py;
        }
    }

    public function SetColor($aColor)
    {
        $this->SetMarginColor($aColor);
    }

    public function SetTitles($aTitleArray)
    {
        $this->axis_title = $aTitleArray;
    }

    public function Add($aPlot)
    {
        if ($aPlot == null) {
            Util\JpGraphError::RaiseL(25010); //("Graph::Add() You tried to add a null plot to the graph.");
        }
        if (is_array($aPlot) && safe_count($aPlot) > 0) {
            $cl = $aPlot[0];
        } else {
            $cl = $aPlot;
        }

        if ($cl instanceof Text\Text) {
            $this->AddText($aPlot);
        } elseif (($cl instanceof Plot\IconPlot)) {
            $this->AddIcon($aPlot);
        } else {
            $this->plots[] = $aPlot;
        }
    }

    public function GetPlotsYMinMax($aPlots)
    {
        $min = $aPlots[0]->Min();
        $max = $aPlots[0]->Max();
        foreach ($this->plots as $p) {
            $max = max($max, $p->Max());
            $min = min($min, $p->Min());
        }
        if ($min < 0) {
            Util\JpGraphError::RaiseL(18006, $min);
            //("Minimum data $min (Radar plots should only be used when all data points > 0)");
        }

        return [$min, $max];
    }

    public function StrokeIcons()
    {
        if ($this->iIcons != null) {
            $n = safe_count($this->iIcons);
            for ($i = 0; $i < $n; ++$i) {
                $this->iIcons[$i]->Stroke($this->img);
            }
        }
    }

    public function StrokeTexts()
    {
        if ($this->texts != null) {
            $n = safe_count($this->texts);
            for ($i = 0; $i < $n; ++$i) {
                $this->texts[$i]->Stroke($this->img);
            }
        }
    }

    // Stroke the Radar graph
    public function Stroke($aStrokeFileName = '')
    {
        // If the filename is the predefined value = '_csim_special_'
        // we assume that the call to stroke only needs to do enough
        // to correctly generate the CSIM maps.
        // We use this variable to skip things we don't strictly need
        // to do to generate the image map to improve performance
        // a best we can. Therefor you will see a lot of tests !$_csim in the
        // code below.
        $_csim = ($aStrokeFileName === _CSIM_SPECIALFILE);

        // We need to know if we have stroked the plot in the
        // GetCSIMareas. Otherwise the CSIM hasn't been generated
        // and in the case of GetCSIM called before stroke to generate
        // CSIM without storing an image to disk GetCSIM must call Stroke.
        $this->iHasStroked = true;

        $n = safe_count($this->plots);
        // Set Y-scale

        if (!$this->yscale->IsSpecified() && safe_count($this->plots) > 0) {
            list($min, $max) = $this->GetPlotsYMinMax($this->plots);
            $this->yscale->AutoScale($this->img, 0, $max, $this->len / $this->ytick_factor);
        } elseif ($this->yscale->IsSpecified() &&
            ($this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified())) {
            // The tick calculation will use the user suplied min/max values to determine
            // the ticks. If auto_ticks is false the exact user specifed min and max
            // values will be used for the scale.
            // If auto_ticks is true then the scale might be slightly adjusted
            // so that the min and max values falls on an even major step.
            $min = $this->yscale->scale[0];
            $max = $this->yscale->scale[1];
            $this->yscale->AutoScale(
                $this->img,
                $min,
                $max,
                $this->len / $this->ytick_factor,
                $this->yscale->auto_ticks
            );
        }

        // Set start position end length of scale (in absolute pixels)
        $this->yscale->SetConstants($this->posx, $this->len);

        // We need as many axis as there are data points
        $nbrpnts = $this->plots[0]->GetCount();

        // If we have no titles just number the axis 1,2,3,...
        if ($this->axis_title == null) {
            for ($i = 0; $i < $nbrpnts; ++$i) {
                $this->axis_title[$i] = $i + 1;
            }
        } elseif (safe_count($this->axis_title) < $nbrpnts) {
            Util\JpGraphError::RaiseL(18007);
            // ("Number of titles does not match number of points in plot.");
        }
        for ($i = 0; $i < $n; ++$i) {
            if ($nbrpnts != $this->plots[$i]->GetCount()) {
                Util\JpGraphError::RaiseL(18008);
                //("Each radar plot must have the same number of data points.");
            }
        }

        if (!$_csim) {
            if ($this->background_image != '') {
                $this->StrokeFrameBackground();
            } else {
                $this->StrokeFrame();
                $this->StrokeBackgroundGrad();
            }
        }
        $astep = 2 * M_PI / $nbrpnts;

        if (!$_csim) {
            if ($this->iIconDepth == DEPTH_BACK) {
                $this->StrokeIcons();
            }

            // Prepare legends
            for ($i = 0; $i < $n; ++$i) {
                $this->plots[$i]->Legend($this);
            }
            $this->legend->Stroke($this->img);
            $this->footer->Stroke($this->img);
        }

        if (!$_csim) {
            if ($this->grid_depth == DEPTH_BACK) {
                // Draw axis and grid
                for ($i = 0, $a = M_PI / 2; $i < $nbrpnts; ++$i, $a += $astep) {
                    $this->axis->Stroke($this->posy, $a, $grid[$i], $this->axis_title[$i], $i == 0);
                }
                $this->grid->Stroke($this->img, $grid);
            }
            if ($this->iIconDepth == DEPTH_BACK) {
                $this->StrokeIcons();
            }
        }

        // Plot points
        $a = M_PI / 2;
        for ($i = 0; $i < $n; ++$i) {
            $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a);
        }

        if (!$_csim) {
            if ($this->grid_depth != DEPTH_BACK) {
                // Draw axis and grid
                for ($i = 0, $a = M_PI / 2; $i < $nbrpnts; ++$i, $a += $astep) {
                    $this->axis->Stroke($this->posy, $a, $grid[$i], $this->axis_title[$i], $i == 0);
                }
                $this->grid->Stroke($this->img, $grid);
            }

            $this->StrokeTitles();
            $this->StrokeTexts();
            if ($this->iIconDepth == DEPTH_FRONT) {
                $this->StrokeIcons();
            }
        }

        // Should we do any final image transformation
        if ($this->iImgTrans && !$_csim) {
            $tform          = new Image\ImgTrans($this->img->img);
            $this->img->img = $tform->Skew3D(
                $this->iImgTransHorizon,
                $this->iImgTransSkewDist,
                $this->iImgTransDirection,
                $this->iImgTransHighQ,
                $this->iImgTransMinSize,
                $this->iImgTransFillColor,
                $this->iImgTransBorder
            );
        }

        if (!$_csim) {
            // If the filename is given as the special "__handle"
            // then the image handler is returned and the image is NOT
            // streamed back
            if ($aStrokeFileName == _IMG_HANDLER) {
                return $this->img->img;
            }
            // Finally stream the generated picture
            $this->cache->PutAndStream($this->img, $this->cache_name, $this->inline, $aStrokeFileName);
        }
    }
} // @class