<?
/**
* Width of the page used, in this case A4 size in centimetres
*/
define ("SIZEWIDTHCM",21);
/**
* Height of the page used, in this case A4 size in centimetres
*/
define ("SIZEHEIGHTCM",27);
/**
* Left Margin
*/
define ("BEGINXSVG",10);
/**
* Top Margin
*/
define ("BEGINYSVG",30);
/**
* Characters to be displayed in a line
*/
define ("MAXCHARACTERS",30);
/**
* This class is used to represent the information using the svg format
*/
class CDataChart
{
var $m_arrAttributes = array();
var $m_arrObjects = array();
function GetMinAttribute($strAttribute)
{
if (count($this->m_arrObjects) == 0)
return 0;
$valueMin =$this->m_arrObjects[0]->$strAttribute;
reset($this->m_arrObjects);
while (list($key, $object) = each($this->m_arrObjects))
{
$valueAct =$object->$strAttribute;
if ($valueAct < $valueMin)
{
$valueMin=$valueAct;
}
}
return $valueMin;
}
function GetMaxAttribute($strAttribute)
{
if (count($this->m_arrObjects) == 0)
return 0;
$valueMax =$this->m_arrObjects[0]->$strAttribute;
reset($this->m_arrObjects);
while (list($key, $object) = each($this->m_arrObjects))
{
$valueAct =$object->$strAttribute;
if ($valueAct > $valueMax)
{
$valueMax=$valueAct;
}
}
return $valueMax;
}
function GetNumAttributes()
{
return $this->m_arrAttributes;
}
}
class CCircleChart
{
/**
* Data
*/
var $m_dataChart;
/**
* Width of the page
*/
var $m_nWidthSVG =SIZEWIDTHCM;
/**
* Height of the page
*/
var $m_nHeightSVG =SIZEHEIGHTCM;
/**
* Coord Center X of the data circle
*/
var $m_nCenterX;
/**
* Coord Center Y of the data circle
*/
var $m_nCenterY;
/**
* Radius of the data circle
*/
var $m_nRadius;
/**
* Coord Center X of the attributes circle
*/
var $m_nCenterXAttributes;
/**
* Coord Center Y of the attributes circle
*/
var $m_nCenterYAttributes;
/**
* Radius of the attributes circle
*/
var $m_nRadiusAttributes;
/**
* Constructor of the class
*/
function CCircleChart($strPath)
{
$this->m_dataChart = new CDataChart();
$this->m_strPath =$strPath;
$strPathTemp =sprintf("%s",$this->m_strPath);
$this->m_fileSVG = @fopen($strPathTemp,"w");
}
/**
* Write to the file the standard svg headers, if you want use another measure units
* you have to change them here
*/
function HeaderSVG()
{
$strHeaderSVG ="<?xml version=\"1.0\" standalone=\"no\"?>";
$strHeaderSVG .="<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ";
$strHeaderSVG .="\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">";
$strTemp =sprintf("<svg width=\"%dcm\" height=\"%dcm\" viewBox=\"0 0 %d %d\" ",
$this->m_nWidthSVG,$this->m_nHeightSVG,
$this->m_nWidthSVG*100,$this->m_nHeightSVG*100);
$strHeaderSVG .=$strTemp;
$strHeaderSVG .="xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n";
fwrite($this->m_fileSVG,$strHeaderSVG);
}
/**
* Close the actual svg file, and write the last of svg end
*/
function CloseSVG()
{
fwrite($this->m_fileSVG,"</svg>");
fclose($this->m_fileSVG);
}
/**
* Adjust the "normal" coordX to the SVG axis
*/
function ConvertXtoXSVG($nX)
{
return $nX;
}
/**
* Adjust the "normal" coordY to the SVG axis
*/
function ConvertYtoYSVG($nY)
{
return $this->m_nHeightSVG*100 - $nY;
}
/**
* Draw a circle using the parameters
*/
function DrawCircle($nCenterX,$nCenterY,$nRadius,$strFill,$strStroke,$nStrokeWidth,$strDashArray,$strEvents = "")
{
$nCenterXSVG =$this->ConvertXtoXSVG($nCenterX);
$nCenterYSVG =$this->ConvertYtoYSVG($nCenterY);
fwrite($this->m_fileSVG,"<circle cx=\"$nCenterXSVG\" cy=\"$nCenterYSVG\" r=\"$nRadius\" ");
fwrite($this->m_fileSVG," style=\"fill$strFill;stroke$strStroke;stroke-width:$nStrokeWidth;stroke-dasharray:$strDashArray\"");
fwrite($this->m_fileSVG," $strEvents/>\n");
}
/**
* Calculate the coords corresponding to an angle of a circle
*/
function CalcAngle($nCenterX,$nCenterY,$nRadius,$nAngle,&$nPosX,&$nPosY)
{
$nAngleRad =$nAngle * 2 * pi() / 360;
$nPosX =(int)(cos($nAngleRad)*$nRadius + $nCenterX);
$nPosY =(int)(sin($nAngleRad)*$nRadius + $nCenterY);
}
/**
* Draw a line from the center to an angle of the circle
*/
function LineCircle($nCenterX,$nCenterY,$nRadius,$nAngle,$strFill,$strStroke,$nStrokeWidth,$strDashArray)
{
$nAngleRad =$nAngle * 2 * pi() / 360;
$nPosX =(int)(cos($nAngleRad)*$nRadius + $nCenterX);
$nPosY =(int)(sin($nAngleRad)*$nRadius + $nCenterY);
$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
$nCenterXSVG =$this->ConvertXtoXSVG($nCenterX);
$nCenterYSVG =$this->ConvertYtoYSVG($nCenterY);
fwrite($this->m_fileSVG,"<line x1=\"$nCenterXSVG\" y1=\"$nCenterYSVG\" x2=\"$nPosXSVG\" y2=\"$nPosYSVG\" ");
fwrite($this->m_fileSVG,"fill=\"$strFill\" stroke=\"$strStroke\" stroke-width=\"$nStrokeWidth\" stroke-dasharray=\"$strDashArray\" />\n");
}
/**
* Draw a text using the parameters
*/
function Text($strText,$nPosX,$nPosY,$strFont,$nFontSize,$strFill,$strAnchor)
{
$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
fwrite($this->m_fileSVG,"<text x=\"$nPosXSVG\" y=\"$nPosYSVG\" font-family=\"$strFont\" font-size=\"$nFontSize\" ");
fwrite($this->m_fileSVG,"fill=\"$strFill\" text-anchor=\"$strAnchor\">$strText</text>\n");
}
/**
* Draw a text with id using the parameters to change it dinamically
*/
function TextId($strId,$strText,$nPosX,$nPosY,$strFont,$nFontSize,$strFill,$strAnchor)
{
$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
fwrite($this->m_fileSVG,"<text id=\"$strId\" x=\"$nPosXSVG\" y=\"$nPosYSVG\" font-family=\"$strFont\" font-size=\"$nFontSize\" ");
fwrite($this->m_fileSVG,"fill=\"$strFill\" text-anchor=\"$strAnchor\">$strText</text>\n");
}
/**
* Calculate the lenght of an arc
*/
function GetArcLength($nCenterX,$nCenterY,$nRadius,$nAngle)
{
$this->CalcAngle($nCenterX,$nCenterY,$nRadius,$nAngle,$nPosX,$nPosY);
$this->CalcAngle($nCenterX,$nCenterY,$nRadius,2*$nAngle,$nPosX2,$nPosY2);
return sqrt(pow(abs($nPosX - $nPosX2),2) + pow(abs($nPosY - $nPosY2),2)) / 2;
}
/**
* Draw the lines from the data positions to center
*/
function LinesToCenter()
{
$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
$nAngle =90;
for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
{
$this->LineCircle($this->m_nCenterX,$this->m_nCenterY,$this->m_nRadius,$nAngle,"blue","red",5,"10 5");
$nAngle =$nAngle + $nVarAngle;
}
}
/**
* Draw the text of the attributes circle
*/
function TextData()
{
$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
$nAngle =90;
$nArcLength =20 + $this->m_nRadius + $this->GetArcLength($this->m_nCenterX,$this->m_nCenterY,$this->m_nRadius,$nVarAngle);
for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
{
$strIndexAct =$this->m_dataChart->m_arrObjects[$j]->m_strIndex;
$this->CalcAngle($this->m_nCenterXAttributes,$this->m_nCenterYAttributes,
$this->m_nRadiusAttributes+20,$nAngle,$nPosX,$nPosY);
$this->Text($strIndexAct,$nPosX,$nPosY,"Verdana",20,"black","middle");
$this->CalcAngle($this->m_nCenterX,$this->m_nCenterY-15,
$nArcLength,$nAngle,$nPosX,$nPosY);
$this->Text($strIndexAct,$nPosX,$nPosY,"Verdana",20,"black","middle");
$nAngle =$nAngle + $nVarAngle;
}
$this->TextId("index","INDEX",$this->m_nCenterXAttributes,$this->m_nCenterYAttributes-30,"Verdana",30,"black","middle");
}
/**
* Draw the data in the data circle
*/
function DrawData()
{
$nRadius =$this->m_nRadius;
$nRadiusAttributes =$this->m_nRadiusAttributes;
$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
$nVarRadius =$nRadius / count($this->m_dataChart->m_arrAttributes);
$nVarRadiusAttributes =$nRadiusAttributes / count($this->m_dataChart->m_arrAttributes);
for($i=0;$i<count($this->m_dataChart->m_arrAttributes);$i++)
{
$nAngle =90;
$strAttribute =$this->m_dataChart->m_arrAttributes[$i];
$valueMin =$this->m_dataChart->GetMinAttribute($strAttribute);
$valueMax =$this->m_dataChart->GetMaxAttribute($strAttribute);
$valueMed =$valueMin + ($valueMax - $valueMin)/2;
$nArcLength =$this->GetArcLength($this->m_nCenterX,$this->m_nCenterY,$nRadius,$nVarAngle);
$maxArea =pi() * pow($nArcLength,2);
$this->Text($strAttribute,$this->m_nCenterXAttributes,$this->m_nCenterYAttributes + $nRadiusAttributes -30,"Verdana",20,"black","middle");
$this->TextId($strAttribute,"DATA",$this->m_nCenterXAttributes,$this->m_nCenterYAttributes + $nRadiusAttributes-60,"Verdana",25,"black","middle");
for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
{
$valueAct =$this->m_dataChart->m_arrObjects[$j]->$strAttribute;
$nRadiusAct =sqrt(($maxArea*$valueAct)/(pi()*$valueMax));
$this->CalcAngle($this->m_nCenterX,$this->m_nCenterY,$nRadius,$nAngle,$nPosX,$nPosY);
if ($valueAct < $valueMed)
{
$nColor =255 * (1-($valueAct - $valueMin)/($valueMax - $valueMin));
$strColor =":rgb(0,$nColor,0)";
}
else
{
$nColor =255 * (1-($valueAct - $valueMin)/($valueMax - $valueMin));
$strColor =":rgb(0,$nColor,0)";
}
$strEvents=" onmouseover=\"change" .$this->m_dataChart->m_arrObjects[$j]->m_strIndex ."(evt)\"";
$this->DrawCircle($nPosX,$nPosY,$nRadiusAct,$strColor,":rgb(0,255,0)",3,"5 5",$strEvents);
$nAngle =$nAngle + $nVarAngle;
}
$nRadius =$nRadius - $nVarRadius;
$nRadiusAttributes =$nRadiusAttributes - $nVarRadiusAttributes;
}
}
/**
* Generate the scripts to link the data circle and the attributes circle
* Be careful with the names
*/
function GenScripts()
{
fwrite($this->m_fileSVG,"<script type=\"text/ecmascript\"><![CDATA[\n");
for ($i=0;$i<count($this->m_dataChart->m_arrObjects);$i++)
{
$strIndex =$this->m_dataChart->m_arrObjects[$i]->m_strIndex;
fwrite($this->m_fileSVG,"function change" . $strIndex ."(evt){\n");
fwrite($this->m_fileSVG,"var svgdoc=evt.target.getOwnerDocument();\n");
for ($j=0;$j<count($this->m_dataChart->m_arrAttributes);$j++)
{
$strAttribute =$this->m_dataChart->m_arrAttributes[$j];
fwrite($this->m_fileSVG,"newText = svgdoc.createTextNode(\"" . $this->m_dataChart->m_arrObjects[$i]->$strAttribute. "\");\n");
fwrite($this->m_fileSVG,"svgobj =svgdoc.getElementById('$strAttribute');\n");
fwrite($this->m_fileSVG,"svgobj.replaceChild(newText,svgobj.getFirstChild());\n");
}
fwrite($this->m_fileSVG,"newText = svgdoc.createTextNode(\"" . $this->m_dataChart->m_arrObjects[$i]->m_strIndex. "\");\n");
fwrite($this->m_fileSVG,"svgobj =svgdoc.getElementById('index');\n");
fwrite($this->m_fileSVG,"svgobj.replaceChild(newText,svgobj.getFirstChild());\n");
fwrite($this->m_fileSVG, "}\n");
}
fwrite($this->m_fileSVG,"]]></script>\n");
}
}
//************************************************************************
?>