forkad från vergnet/site-accueil-insa
532 rader
21 KiB
PHP
532 rader
21 KiB
PHP
<?php
|
|
|
|
namespace CpChart\Chart;
|
|
|
|
use CpChart\Data;
|
|
use CpChart\Image;
|
|
|
|
/**
|
|
* Bubble - class to draw bubble charts
|
|
*
|
|
* Version : 2.1.4
|
|
* Made by : Jean-Damien POGOLOTTI
|
|
* Last Update : 19/01/2014
|
|
*
|
|
* This file can be distributed under the license you can find at :
|
|
*
|
|
* http://www.pchart.net/license
|
|
*
|
|
* You can find the whole class documentation on the pChart web site.
|
|
*/
|
|
class Bubble
|
|
{
|
|
/**
|
|
* @var Image
|
|
*/
|
|
public $pChartObject;
|
|
|
|
/**
|
|
* @var Data
|
|
*/
|
|
public $pDataObject;
|
|
|
|
/**
|
|
* @param Image $pChartObject
|
|
* @param Data $pDataObject
|
|
*/
|
|
public function __construct(Image $pChartObject, Data $pDataObject)
|
|
{
|
|
$this->pChartObject = $pChartObject;
|
|
$this->pDataObject = $pDataObject;
|
|
}
|
|
|
|
/**
|
|
* Prepare the scale
|
|
*
|
|
* @param mixed $DataSeries
|
|
* @param mixed $WeightSeries
|
|
*/
|
|
public function bubbleScale($DataSeries, $WeightSeries)
|
|
{
|
|
if (!is_array($DataSeries)) {
|
|
$DataSeries = [$DataSeries];
|
|
}
|
|
if (!is_array($WeightSeries)) {
|
|
$WeightSeries = [$WeightSeries];
|
|
}
|
|
|
|
/* Parse each data series to find the new min & max boundaries to scale */
|
|
$NewPositiveSerie = [];
|
|
$NewNegativeSerie = [];
|
|
$MaxValues = 0;
|
|
$LastPositive = 0;
|
|
$LastNegative = 0;
|
|
|
|
foreach ($DataSeries as $Key => $SerieName) {
|
|
$SerieWeightName = $WeightSeries[$Key];
|
|
|
|
$this->pDataObject->setSerieDrawable($SerieWeightName, false);
|
|
$serieData = $this->pDataObject->Data["Series"][$SerieName]["Data"];
|
|
if (count($serieData) > $MaxValues) {
|
|
$MaxValues = count($serieData);
|
|
}
|
|
|
|
foreach ($serieData as $Key => $Value) {
|
|
if ($Value >= 0) {
|
|
$BubbleBounds = $Value + $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key];
|
|
|
|
if (!isset($NewPositiveSerie[$Key])) {
|
|
$NewPositiveSerie[$Key] = $BubbleBounds;
|
|
} elseif ($NewPositiveSerie[$Key] < $BubbleBounds) {
|
|
$NewPositiveSerie[$Key] = $BubbleBounds;
|
|
}
|
|
$LastPositive = $BubbleBounds;
|
|
} else {
|
|
$BubbleBounds = $Value - $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key];
|
|
|
|
if (!isset($NewNegativeSerie[$Key])) {
|
|
$NewNegativeSerie[$Key] = $BubbleBounds;
|
|
} elseif ($NewNegativeSerie[$Key] > $BubbleBounds) {
|
|
$NewNegativeSerie[$Key] = $BubbleBounds;
|
|
}
|
|
$LastNegative = $BubbleBounds;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check for missing values and all the fake positive serie */
|
|
if (count($NewPositiveSerie)) {
|
|
for ($i = 0; $i < $MaxValues; $i++) {
|
|
if (!isset($NewPositiveSerie[$i])) {
|
|
$NewPositiveSerie[$i] = $LastPositive;
|
|
}
|
|
}
|
|
$this->pDataObject->addPoints($NewPositiveSerie, "BubbleFakePositiveSerie");
|
|
}
|
|
|
|
/* Check for missing values and all the fake negative serie */
|
|
if (count($NewNegativeSerie)) {
|
|
for ($i = 0; $i < $MaxValues; $i++) {
|
|
if (!isset($NewNegativeSerie[$i])) {
|
|
$NewNegativeSerie[$i] = $LastNegative;
|
|
}
|
|
}
|
|
|
|
$this->pDataObject->addPoints($NewNegativeSerie, "BubbleFakeNegativeSerie");
|
|
}
|
|
}
|
|
|
|
public function resetSeriesColors()
|
|
{
|
|
$Data = $this->pDataObject->getData();
|
|
$Palette = $this->pDataObject->getPalette();
|
|
|
|
$ID = 0;
|
|
foreach ($Data["Series"] as $SerieName => $SeriesParameters) {
|
|
if ($SeriesParameters["isDrawable"]) {
|
|
$this->pDataObject->Data["Series"][$SerieName]["Color"]["R"] = $Palette[$ID]["R"];
|
|
$this->pDataObject->Data["Series"][$SerieName]["Color"]["G"] = $Palette[$ID]["G"];
|
|
$this->pDataObject->Data["Series"][$SerieName]["Color"]["B"] = $Palette[$ID]["B"];
|
|
$this->pDataObject->Data["Series"][$SerieName]["Color"]["Alpha"] = $Palette[$ID]["Alpha"];
|
|
$ID++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Prepare the scale */
|
|
|
|
public function drawBubbleChart($DataSeries, $WeightSeries, $Format = "")
|
|
{
|
|
$ForceAlpha = isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : VOID;
|
|
$DrawBorder = isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : true;
|
|
$BorderWidth = isset($Format["BorderWidth"]) ? $Format["BorderWidth"] : 1;
|
|
$Shape = isset($Format["Shape"]) ? $Format["Shape"] : BUBBLE_SHAPE_ROUND;
|
|
$Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : null;
|
|
$BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0;
|
|
$BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0;
|
|
$BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0;
|
|
$BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30;
|
|
$RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : false;
|
|
|
|
if (!is_array($DataSeries)) {
|
|
$DataSeries = [$DataSeries];
|
|
}
|
|
if (!is_array($WeightSeries)) {
|
|
$WeightSeries = [$WeightSeries];
|
|
}
|
|
|
|
$Data = $this->pDataObject->getData();
|
|
$Palette = $this->pDataObject->getPalette();
|
|
|
|
if (isset($Data["Series"]["BubbleFakePositiveSerie"])) {
|
|
$this->pDataObject->setSerieDrawable("BubbleFakePositiveSerie", false);
|
|
}
|
|
if (isset($Data["Series"]["BubbleFakeNegativeSerie"])) {
|
|
$this->pDataObject->setSerieDrawable("BubbleFakeNegativeSerie", false);
|
|
}
|
|
|
|
$this->resetSeriesColors();
|
|
|
|
list($XMargin, $XDivs) = $this->pChartObject->scaleGetXSettings();
|
|
|
|
foreach ($DataSeries as $Key => $SerieName) {
|
|
$AxisID = $Data["Series"][$SerieName]["Axis"];
|
|
$Mode = $Data["Axis"][$AxisID]["Display"];
|
|
$Format = $Data["Axis"][$AxisID]["Format"];
|
|
$Unit = $Data["Axis"][$AxisID]["Unit"];
|
|
|
|
if (isset($Data["Series"][$SerieName]["Description"])) {
|
|
$SerieDescription = $Data["Series"][$SerieName]["Description"];
|
|
} else {
|
|
$SerieDescription = $SerieName;
|
|
}
|
|
|
|
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2) / $XDivs;
|
|
|
|
$X = $this->pChartObject->GraphAreaX1 + $XMargin;
|
|
$Y = $this->pChartObject->GraphAreaY1 + $XMargin;
|
|
|
|
$Color = [
|
|
"R" => $Palette[$Key]["R"],
|
|
"G" => $Palette[$Key]["G"],
|
|
"B" => $Palette[$Key]["B"],
|
|
"Alpha" => $Palette[$Key]["Alpha"]
|
|
];
|
|
|
|
if ($ForceAlpha != VOID) {
|
|
$Color["Alpha"] = $ForceAlpha;
|
|
}
|
|
|
|
if ($DrawBorder) {
|
|
if ($BorderWidth != 1) {
|
|
if ($Surrounding != null) {
|
|
$BorderR = $Palette[$Key]["R"] + $Surrounding;
|
|
$BorderG = $Palette[$Key]["G"] + $Surrounding;
|
|
$BorderB = $Palette[$Key]["B"] + $Surrounding;
|
|
}
|
|
if ($ForceAlpha != VOID) {
|
|
$BorderAlpha = $ForceAlpha / 2;
|
|
}
|
|
$BorderColor = [
|
|
"R" => $BorderR,
|
|
"G" => $BorderG,
|
|
"B" => $BorderB,
|
|
"Alpha" => $BorderAlpha
|
|
];
|
|
} else {
|
|
$Color["BorderAlpha"] = $BorderAlpha;
|
|
|
|
if ($Surrounding != null) {
|
|
$Color["BorderR"] = $Palette[$Key]["R"] + $Surrounding;
|
|
$Color["BorderG"] = $Palette[$Key]["G"] + $Surrounding;
|
|
$Color["BorderB"] = $Palette[$Key]["B"] + $Surrounding;
|
|
} else {
|
|
$Color["BorderR"] = $BorderR;
|
|
$Color["BorderG"] = $BorderG;
|
|
$Color["BorderB"] = $BorderB;
|
|
}
|
|
if ($ForceAlpha != VOID) {
|
|
$Color["BorderAlpha"] = $ForceAlpha / 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($Data["Series"][$SerieName]["Data"] as $iKey => $Point) {
|
|
$Weight = $Point + $Data["Series"][$WeightSeries[$Key]]["Data"][$iKey];
|
|
|
|
$PosArray = $this->pChartObject->scaleComputeY(
|
|
$Point,
|
|
["AxisID" => $AxisID]
|
|
);
|
|
$WeightArray = $this->pChartObject->scaleComputeY(
|
|
$Weight,
|
|
["AxisID" => $AxisID]
|
|
);
|
|
|
|
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
|
|
if ($XDivs == 0) {
|
|
$XStep = 0;
|
|
} else {
|
|
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2)
|
|
/ $XDivs
|
|
;
|
|
}
|
|
$Y = floor($PosArray);
|
|
$CircleRadius = floor(abs($PosArray - $WeightArray) / 2);
|
|
|
|
if ($Shape == BUBBLE_SHAPE_SQUARE) {
|
|
if ($RecordImageMap) {
|
|
$this->pChartObject->addToImageMap(
|
|
"RECT",
|
|
(
|
|
floor($X - $CircleRadius)
|
|
. "," . floor($Y - $CircleRadius)
|
|
. "," . floor($X + $CircleRadius)
|
|
. "," . floor($Y + $CircleRadius)
|
|
),
|
|
$this->pChartObject->toHTMLColor(
|
|
$Palette[$Key]["R"],
|
|
$Palette[$Key]["G"],
|
|
$Palette[$Key]["B"]
|
|
),
|
|
$SerieDescription,
|
|
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
|
|
);
|
|
}
|
|
|
|
if ($BorderWidth != 1) {
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius - $BorderWidth,
|
|
$Y - $CircleRadius - $BorderWidth,
|
|
$X + $CircleRadius + $BorderWidth,
|
|
$Y + $CircleRadius + $BorderWidth,
|
|
$BorderColor
|
|
);
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius,
|
|
$Y - $CircleRadius,
|
|
$X + $CircleRadius,
|
|
$Y + $CircleRadius,
|
|
$Color
|
|
);
|
|
} else {
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius,
|
|
$Y - $CircleRadius,
|
|
$X + $CircleRadius,
|
|
$Y + $CircleRadius,
|
|
$Color
|
|
);
|
|
}
|
|
} elseif ($Shape == BUBBLE_SHAPE_ROUND) {
|
|
if ($RecordImageMap) {
|
|
$this->pChartObject->addToImageMap(
|
|
"CIRCLE",
|
|
floor($X) . "," . floor($Y) . "," . floor($CircleRadius),
|
|
$this->pChartObject->toHTMLColor(
|
|
$Palette[$Key]["R"],
|
|
$Palette[$Key]["G"],
|
|
$Palette[$Key]["B"]
|
|
),
|
|
$SerieDescription,
|
|
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
|
|
);
|
|
}
|
|
|
|
if ($BorderWidth != 1) {
|
|
$this->pChartObject->drawFilledCircle(
|
|
$X,
|
|
$Y,
|
|
$CircleRadius + $BorderWidth,
|
|
$BorderColor
|
|
);
|
|
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
|
|
} else {
|
|
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
|
|
}
|
|
}
|
|
|
|
$X = $X + $XStep;
|
|
} elseif ($Data["Orientation"] == SCALE_POS_TOPBOTTOM) {
|
|
if ($XDivs == 0) {
|
|
$XStep = 0;
|
|
} else {
|
|
$XStep = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $XMargin * 2)
|
|
/ $XDivs
|
|
;
|
|
}
|
|
$X = floor($PosArray);
|
|
$CircleRadius = floor(abs($PosArray - $WeightArray) / 2);
|
|
|
|
if ($Shape == BUBBLE_SHAPE_SQUARE) {
|
|
if ($RecordImageMap) {
|
|
$this->pChartObject->addToImageMap(
|
|
"RECT",
|
|
(
|
|
floor($X - $CircleRadius) . ","
|
|
. floor($Y - $CircleRadius) . ","
|
|
. floor($X + $CircleRadius) . ","
|
|
. floor($Y + $CircleRadius)
|
|
),
|
|
$this->pChartObject->toHTMLColor(
|
|
$Palette[$Key]["R"],
|
|
$Palette[$Key]["G"],
|
|
$Palette[$Key]["B"]
|
|
),
|
|
$SerieDescription,
|
|
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
|
|
);
|
|
}
|
|
|
|
if ($BorderWidth != 1) {
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius - $BorderWidth,
|
|
$Y - $CircleRadius - $BorderWidth,
|
|
$X + $CircleRadius + $BorderWidth,
|
|
$Y + $CircleRadius + $BorderWidth,
|
|
$BorderColor
|
|
);
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius,
|
|
$Y - $CircleRadius,
|
|
$X + $CircleRadius,
|
|
$Y + $CircleRadius,
|
|
$Color
|
|
);
|
|
} else {
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - $CircleRadius,
|
|
$Y - $CircleRadius,
|
|
$X + $CircleRadius,
|
|
$Y + $CircleRadius,
|
|
$Color
|
|
);
|
|
}
|
|
} elseif ($Shape == BUBBLE_SHAPE_ROUND) {
|
|
if ($RecordImageMap) {
|
|
$this->pChartObject->addToImageMap(
|
|
"CIRCLE",
|
|
floor($X) . "," . floor($Y) . "," . floor($CircleRadius),
|
|
$this->pChartObject->toHTMLColor(
|
|
$Palette[$Key]["R"],
|
|
$Palette[$Key]["G"],
|
|
$Palette[$Key]["B"]
|
|
),
|
|
$SerieDescription,
|
|
$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]
|
|
);
|
|
}
|
|
|
|
if ($BorderWidth != 1) {
|
|
$this->pChartObject->drawFilledCircle(
|
|
$X,
|
|
$Y,
|
|
$CircleRadius + $BorderWidth,
|
|
$BorderColor
|
|
);
|
|
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
|
|
} else {
|
|
$this->pChartObject->drawFilledCircle($X, $Y, $CircleRadius, $Color);
|
|
}
|
|
}
|
|
|
|
$Y = $Y + $XStep;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function writeBubbleLabel($SerieName, $SerieWeightName, $Points, $Format = "")
|
|
{
|
|
$DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX;
|
|
|
|
if (!is_array($Points)) {
|
|
$Point = $Points;
|
|
$Points = [];
|
|
$Points[] = $Point;
|
|
}
|
|
|
|
$Data = $this->pDataObject->getData();
|
|
|
|
if (!isset($Data["Series"][$SerieName])
|
|
|| !isset($Data["Series"][$SerieWeightName])
|
|
) {
|
|
return(0);
|
|
}
|
|
list($XMargin, $XDivs) = $this->pChartObject->scaleGetXSettings();
|
|
|
|
$AxisID = $Data["Series"][$SerieName]["Axis"];
|
|
$AxisMode = $Data["Axis"][$AxisID]["Display"];
|
|
$AxisFormat = $Data["Axis"][$AxisID]["Format"];
|
|
$AxisUnit = $Data["Axis"][$AxisID]["Unit"];
|
|
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2) / $XDivs;
|
|
|
|
$X = $InitialX = $this->pChartObject->GraphAreaX1 + $XMargin;
|
|
$Y = $InitialY = $this->pChartObject->GraphAreaY1 + $XMargin;
|
|
|
|
$Color = [
|
|
"R" => $Data["Series"][$SerieName]["Color"]["R"],
|
|
"G" => $Data["Series"][$SerieName]["Color"]["G"],
|
|
"B" => $Data["Series"][$SerieName]["Color"]["B"],
|
|
"Alpha" => $Data["Series"][$SerieName]["Color"]["Alpha"]
|
|
];
|
|
|
|
foreach ($Points as $Key => $Point) {
|
|
$Value = $Data["Series"][$SerieName]["Data"][$Point];
|
|
$PosArray = $this->pChartObject->scaleComputeY($Value, ["AxisID" => $AxisID]);
|
|
|
|
if (isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Point])) {
|
|
$Abscissa = $Data["Series"][$Data["Abscissa"]]["Data"][$Point] . " : ";
|
|
} else {
|
|
$Abscissa = "";
|
|
}
|
|
$Value = $this->pChartObject->scaleFormat($Value, $AxisMode, $AxisFormat, $AxisUnit);
|
|
$Weight = $Data["Series"][$SerieWeightName]["Data"][$Point];
|
|
$Caption = $Abscissa . $Value . " / " . $Weight;
|
|
|
|
if (isset($Data["Series"][$SerieName]["Description"])) {
|
|
$Description = $Data["Series"][$SerieName]["Description"];
|
|
} else {
|
|
$Description = "No description";
|
|
}
|
|
$Series = [["Format" => $Color, "Caption" => $Caption]];
|
|
|
|
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
|
|
if ($XDivs == 0) {
|
|
$XStep = 0;
|
|
} else {
|
|
$XStep = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin * 2)
|
|
/ $XDivs
|
|
;
|
|
}
|
|
|
|
$X = floor($InitialX + $Point * $XStep);
|
|
$Y = floor($PosArray);
|
|
} else {
|
|
if ($XDivs == 0) {
|
|
$YStep = 0;
|
|
} else {
|
|
$YStep = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $XMargin * 2)
|
|
/ $XDivs
|
|
;
|
|
}
|
|
|
|
$X = floor($PosArray);
|
|
$Y = floor($InitialY + $Point * $YStep);
|
|
}
|
|
|
|
if ($DrawPoint == LABEL_POINT_CIRCLE) {
|
|
$this->pChartObject->drawFilledCircle(
|
|
$X,
|
|
$Y,
|
|
3,
|
|
[
|
|
"R" => 255,
|
|
"G" => 255,
|
|
"B" => 255,
|
|
"BorderR" => 0,
|
|
"BorderG" => 0,
|
|
"BorderB" => 0
|
|
]
|
|
);
|
|
} elseif ($DrawPoint == LABEL_POINT_BOX) {
|
|
$this->pChartObject->drawFilledRectangle(
|
|
$X - 2,
|
|
$Y - 2,
|
|
$X + 2,
|
|
$Y + 2,
|
|
[
|
|
"R" => 255,
|
|
"G" => 255,
|
|
"B" => 255,
|
|
"BorderR" => 0,
|
|
"BorderG" => 0,
|
|
"BorderB" => 0
|
|
]
|
|
);
|
|
}
|
|
|
|
$this->pChartObject->drawLabelBox($X, $Y - 3, $Description, $Series, $Format);
|
|
}
|
|
}
|
|
}
|