Files
DomFramework/src/GraphStyleLinePoints.php

419 lines
13 KiB
PHP

<?php
/**
* DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/**
* The graphStyleLine : draw a graph with lines
*/
class GraphStyleLinePoints
{
/**
* The line color. To hide the lines, choose "transparent"
*/
protected $lineColor;
/**
* The point color background. To hide the points, choose "transparent"
*/
protected $pointBgcolor;
/**
* The point color border
*/
protected $pointColor;
/**
* The point shape (square, circle, triangle, lozenge)
*/
protected $pointShape;
/**
* The point width in pixel
*/
protected $pointWidth;
/**
* The number of the colors/shapes to use
*/
protected $number;
/**
* The allowed shapes
*/
protected $allowedShapes = ["square", "circle", "triangle", "lozenge"];
/**
* The palette to use
*/
protected $palette;
/**
* Return the name of the style
*/
public function name()
{
return "lineAndPoints";
}
/**
* Set the line color if the parameter is provided.
* Get the line color if the parameter is not provided
* @param string|null $lineColor The line color
*/
public function lineColor($lineColor = null)
{
if ($lineColor === null) {
return $this->lineColor;
}
if (
! is_string($lineColor) ||
($lineColor !== "transparent" &&
! in_array($lineColor, Color::colorList(), true))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid lineColor provided to line style"
), 406);
}
$this->lineColor = $lineColor;
return $this;
}
/**
* Set the palette to use if the parameter is provided
* Get the palette if the parameter is not provided
* @param string|null $palette The palette to use
*/
public function palette($palette = null)
{
if ($palette === null) {
return $this->palette;
}
if (! is_string($palette)) {
throw new \Exception(dgettext(
"domframework",
"Invalid palette provided to line style"
), 406);
}
$this->palette = $palette;
return $this;
}
/**
* Set the point background color if the parameter is provided.
* Get the point background color if the parameter is not provided
* @param string|null $pointBgcolor The point background color
*/
public function pointBgcolor($pointBgcolor = null)
{
if ($pointBgcolor === null) {
return $this->pointBgcolor;
}
if (
! is_string($pointBgcolor) ||
($pointBgcolor !== "transparent" &&
! in_array($pointBgcolor, Color::colorList(), true))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointBgcolor provided to line style"
), 406);
}
$this->pointBgcolor = $pointBgcolor;
return $this;
}
/**
* Set the point border color if the parameter is provided.
* Get the point border color if the parameter is not provided
* @param string|null $pointColor The point border color
*/
public function pointColor($pointColor = null)
{
if ($pointColor === null) {
return $this->pointColor;
}
if (
! is_string($pointColor) ||
($pointColor !== "transparent" &&
! in_array($pointColor, Color::colorList(), true))
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointColor provided to line style"
), 406);
}
$this->pointColor = $pointColor;
return $this;
}
/**
* Set the point shape if the parameter is provided.
* Get the point shape if the parameter is not provided
* @param string|null $pointShape The point shape
*/
public function pointShape($pointShape = null)
{
if ($pointShape === null) {
return $this->pointShape;
}
if (
! is_string($pointShape) ||
! in_array($pointShape, $this->allowedShapes, true)
) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointShape provided to line style"
), 406);
}
$this->pointShape = $pointShape;
return $this;
}
/**
* Set the point width if the parameter is provided.
* Get the point width if the parameter is not provided
* @param string|null $pointWidth The point width
*/
public function pointWidth($pointWidth = null)
{
if ($pointWidth === null) {
return $this->pointWidth;
}
if (! is_integer($pointWidth) || $pointWidth < 3 || $pointWidth > 20) {
throw new \Exception(dgettext(
"domframework",
"Invalid pointWidth provided to line style"
), 406);
}
$this->pointWidth = $pointWidth;
return $this;
}
/**
* Select the colors, shapes by the serie number.
* Do not change any property if the property is already defined
* If the parameter is not provided, return the value
* @param integer|null $number The serie number
*/
public function number($number = null)
{
if ($number === null) {
return $this->number;
}
if (! is_int($number) || $number < 0) {
throw new \Exception(dgettext(
"domframework",
"Invalid number provided to line style number"
), 406);
}
$this->number = $number;
if ($this->pointShape === null) {
$this->pointShape = $this->allowedShapes[
($number % count($this->allowedShapes))];
}
$palette = GraphPalette::getPalette($this->palette);
if ($this->pointBgcolor === null) {
$this->pointBgcolor = $palette[($number % count($palette))]["bgcolor"];
}
if ($this->pointColor === null) {
$this->pointColor = $palette[($number % count($palette))]["color"];
}
if ($this->lineColor === null) {
$this->lineColor = $palette[($number % count($palette))]["color"];
}
}
/**
* Draw in the $gd resource, in the $free array, the data with the parameter
* of the style
* @param resource $gd The resource to modify
* @param array $free The free space coordinates on the graphic
* @param array $data The data to graph
* @param object $axisX The X axis used to graph
* @param object $axisY The Y axis used to graph
*/
public function draw($gd, $free, $data, $axisX, $axisY)
{
if ($this->lineColor !== "transparent") {
$lineColor = Color::allocateFromText($gd, $this->lineColor);
}
$lastX = null;
$lastY = null;
foreach ($data as $key => $value) {
$posX = $axisX->position($key);
$posY = $axisY->position($value);
if ($posX === null || $posY === null) {
// NULL position : skip the point
$lastX = null;
$lastY = null;
continue;
}
// Draw the lines between points (except if the last point was null, or
// if the line color is "transparent")
if (
$lastX !== null && $lastY !== null &&
$this->lineColor !== "transparent"
) {
imageline($gd, $lastX, $lastY, $posX, $posY, $lineColor);
// Redraw the old point which was scratch by the new created line
$this->drawPoint($gd, $lastX, $lastY);
}
if ($lastX === null) {
$lastX = $posX;
}
if ($lastY === null) {
$lastY = $posY;
}
// Draw the point. Will overwrite the lines
if ($this->pointWidth === null) {
$this->pointWidth = 6;
}
$this->drawPoint($gd, $posX, $posY);
$lastX = $posX;
$lastY = $posY;
}
}
/**
* Draw a point defined in the property of the class
* @param resource $gd The resource to modify
* @param integer $posX The X position to draw the point
* @param integer $posY The Y position to draw the point
*/
private function drawPoint($gd, $posX, $posY)
{
if ($this->pointColor !== "transparent") {
$pointColor = Color::allocateFromText($gd, $this->pointColor);
}
if ($this->pointBgcolor !== "transparent") {
$pointBgcolor = Color::allocateFromText($gd, $this->pointBgcolor);
}
$half = intval($this->pointWidth / 2);
switch ($this->pointShape) {
case "circle":
if ($this->pointBgcolor !== "transparent") {
imagefilledellipse(
$gd,
$posX,
$posY,
$this->pointWidth,
$this->pointWidth,
$pointBgcolor + 2
);
}
if ($this->pointColor !== "transparent") {
imageellipse(
$gd,
$posX,
$posY,
$this->pointWidth + 2,
$this->pointWidth + 2,
$pointColor
);
}
break;
case "lozenge":
if ($this->pointBgcolor !== "transparent") {
imagefilledpolygon(
$gd,
[$posX - $half - 2, $posY,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY,
$posX, $posY + $half + 2],
4,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagepolygon(
$gd,
[$posX - $half - 2, $posY,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY,
$posX, $posY + $half + 2],
4,
$pointColor
);
}
break;
case "square":
if ($this->pointBgcolor !== "transparent") {
imagefilledrectangle(
$gd,
$posX - $half - 1,
$posY - $half - 1,
$posX + $half + 1,
$posY + $half + 1,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagerectangle(
$gd,
$posX - $half - 1,
$posY - $half - 1,
$posX + $half + 1,
$posY + $half + 1,
$pointColor
);
}
break;
case "triangle":
if ($this->pointBgcolor !== "transparent") {
imagefilledpolygon(
$gd,
[$posX - $half - 2, $posY + $half + 2,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY + $half + 2],
3,
$pointBgcolor
);
}
if ($this->pointColor !== "transparent") {
imagepolygon(
$gd,
[$posX - $half - 2, $posY + $half + 2,
$posX, $posY - $half - 2,
$posX + $half + 2, $posY + $half + 2],
3,
$pointColor
);
}
break;
default:
throw new \Exception(dgettext(
"domframework",
"Unknown pointShape for serie"
), 406);
}
}
/**
* Draw a sample of the style for the legend
* @param resource $gd The resource to modify
* @param integer $x The central position of the sample in x
* @param integer $y The central position of the sample in y
*/
public function sample($gd, $x, $y)
{
if ($this->lineColor !== "transparent") {
$lineColor = Color::allocateFromText($gd, $this->lineColor);
imageline($gd, $x - 10, $y, $x + 10, $y, $lineColor);
}
if ($this->pointWidth === null) {
$this->pointWidth = 6;
}
$this->drawPoint($gd, $x, $y);
}
}