. */ namespace Volkszaehler\View; use Volkszaehler\Interpreter; use Volkszaehler\Model; use Volkszaehler\Util; require_once VZ_DIR . '/lib/vendor/JpGraph/jpgraph.php'; require_once VZ_DIR . '/lib/vendor/JpGraph/jpgraph_scatter.php'; require_once VZ_DIR . '/lib/vendor/JpGraph/jpgraph_date.php'; /** * Plotting and graphing of data on the server side * * This view uses the JpGraph PHP5 plotting library * * @package default * @author Steffen Vogel * @link http://jpgraph.net/ * @todo add caching * @todo rework */ class JpGraph extends View { /** * @var indicator => ynaxis[n] mapping */ protected $axes = array(); protected $channels = array(); /** * @var default width */ protected $width = 800; /** * @var default height */ protected $height = 400; /** * @var color palette for the scatter plots * This are the same colors as in the webfronted */ protected static $colors = array('#83CAFF', '#7E0021', '#579D1C', '#FFD320', '#FF420E', '#004586', '#0084D1', '#C5000B', '#FF950E', '#4B1F6F', '#AECF00', '#314004'); /** * @var JPGrpah handle */ protected $graph; /** * Constructor * * @param HTTP\Request $request * @param HTTP\Response $response * @param string $format one of png, jpeg, gif */ public function __construct(HTTP\Request $request, HTTP\Response $response, $format = 'png') { parent::__construct($request, $response); // to enabled jpgraphs graphical exception handler restore_exception_handler(); if ($this->request->getParameter('width')) { $this->width = $this->request->getParameter('width'); } if ($this->request->getParameter('height')) { $this->height = $this->request->getParameter('height'); } $this->graph = new \Graph($this->width, $this->height); $this->graph->img->SetImgFormat($format); // Specify what scale we want to use, $this->graph->SetScale('datlin'); $this->graph->legend->SetPos(0.1,0.02, 'left', 'top'); $this->graph->legend->SetShadow(FALSE); $this->graph->SetMarginColor('white'); $this->graph->SetYDeltaDist(65); $this->graph->yaxis->SetTitlemargin(36); $this->graph->SetTickDensity(TICKD_DENSE, TICKD_SPARSE); $this->graph->xaxis->SetFont(FF_ARIAL); $this->graph->xaxis->SetLabelAngle(45); $this->graph->xaxis->SetLabelFormatCallback(function($label) { return date('j.n.y G:i', $label); }); if (function_exists('imageantialias')) { $this->graph->img->SetAntiAliasing(); } } /** * Add object to output * * @param mixed $data */ public function add($data) { if ($data instanceof Interpreter\Interpreter) { $this->addData($data); } elseif($data instanceof Interpreter\AggregatorInterpreter) { foreach ($data->getEntity()->getChildren() as $child) { $this->add($child); } } else { // suppress other classes //throw new \Exception('Can\'t show ' . get_class($data)); } } /** * adds new plot to the graph * * @param $obj * @param $data */ public function addData(Interpreter\InterpreterInterface $interpreter){ $data = $interpreter->getValues($this->width/4); if (count($data) > 0) { $count = count($this->channels); $xData = $yData = array(); foreach ($data as $reading) { $xData[] = $reading[0] / 1000; $yData[] = $reading[1]; } // Create the scatter plot $plot = new \ScatterPlot($yData, $xData); $plot->setLegend($interpreter->getEntity()->getProperty('title') . ': [' . $interpreter->getEntity()->getDefinition()->getUnit() . ']'); $plot->SetLinkPoints(TRUE, self::$colors[$count]); $plot->mark->SetColor(self::$colors[$count]); $plot->mark->SetFillColor(self::$colors[$count]); $plot->mark->SetType(MARK_DIAMOND); $plot->mark->SetWidth(1); $axis = $this->getAxisIndex($interpreter->getEntity()); if ($axis >= 0) { $this->graph->AddY($axis, $plot); } else { $this->graph->Add($plot); } $this->channels[] = $interpreter->getEntity(); } } /** * Shows exception * * @todo avoid graph plotting and set content-type to text/plain * @param \Exception $exception */ protected function addException(\Exception $exception) { echo $exception; } /** * check weather a axis for the indicator of $channel exists * * @param \Volkszaehler\Model\Channel $channel */ protected function getAxisIndex(\Volkszaehler\Model\Channel $channel) { $type = $channel->getType(); if (!array_key_exists($type, $this->axes)) { $count = count($this->axes); if ($count == 0) { $this->axes[$type] = -1; $yaxis = $this->graph->yaxis; } else { $this->axes[$type] = $count - 1; $this->graph->SetYScale($this->axes[$type],'lin'); $yaxis = $this->graph->ynaxis[$this->axes[$type]]; } $yaxis->title->Set($channel->getDefinition()->getUnit()); $yaxis->SetFont(FF_ARIAL); $yaxis->title->SetFont(FF_ARIAL); $yaxis->SetTitleMargin('50'); } return $this->axes[$type]; } /** * render graph and send output directly to browser * * headers has been set automatically */ protected function render() { $this->graph->SetMargin(75, (count($this->axes) - 1) * 65 + 10, 20, 90); // display the graph $this->graph->Stroke(); } } ?>