background = false; $this->sum = false; $this->exploderad = 1; $this->exploderad3d = 3; $this->graphheight3d = 12; $this->shiftlegendright = 17*7 + 7 + 10; // count of static chars * px/char + for color rectangle + space $this->drawlegendallow = 1; } function switchlegend($type=false){ if($type && is_numeric($type)){ $this->drawlegendallow = $type; return $this->drawlegendallow; } elseif($this->drawlegendallow == 0){ $this->drawlegendallow = 1; } else { $this->drawlegendallow = 0; } return $this->drawlegendallow; } function AddItem($itemid, $calc_fnc=CALC_FNC_AVG,$color=null, $type=null, $periods_cnt=null) { if($this->type == GRAPH_TYPE_STACKED /* stacked graph */) $drawtype = GRAPH_ITEM_DRAWTYPE_FILLED_REGION; $this->items[$this->num] = get_item_by_itemid($itemid); $this->items[$this->num]['description']=item_description($this->items[$this->num]['description'],$this->items[$this->num]['key_']); $host=get_host_by_hostid($this->items[$this->num]['hostid']); $this->items[$this->num]['host'] = $host['host']; $this->items[$this->num]['color'] = is_null($color) ? 'Dark Green' : $color; $this->items[$this->num]['calc_fnc'] = is_null($calc_fnc) ? CALC_FNC_AVG : $calc_fnc; $this->items[$this->num]['calc_type'] = is_null($type) ? GRAPH_ITEM_SIMPLE : $type; $this->items[$this->num]['periods_cnt'] = is_null($periods_cnt) ? 0 : $periods_cnt; $this->num++; } function selectData(){ $this->data = array(); $now = time(NULL); if(isset($this->stime)){ $this->from_time = $this->stime; $this->to_time = $this->stime + $this->period; } else{ $this->to_time = $now - 3600 * $this->from; $this->from_time = $this->to_time - $this->period; } $p = $this->to_time - $this->from_time; // graph size in time $z = $p - $this->from_time % $p; // $x = $this->sizeX; // graph size in px $strvaluelength = 0; // we need to know how long in px will be our legend for($i=0; $i < $this->num; $i++){ $real_item = get_item_by_itemid($this->items[$i]['itemid']); $type = $this->items[$i]['calc_type']; $from_time = $this->from_time; $to_time = $this->to_time; $sql_arr = array(); if((($real_item['history']*86400) > (time()-($from_time+$this->period/2))) && // should pick data from history or trends (($this->period / $this->sizeX) <= (ZBX_MAX_TREND_DIFF / ZBX_GRAPH_MAX_SKIP_CELL))) // is reasonable to take data from history? { array_push($sql_arr, 'SELECT h.itemid, '. ' avg(h.value) AS avg,min(h.value) AS min, '. ' max(h.value) AS max,max(h.clock) AS clock, max(i.lastvalue) as lst '. ' FROM history h '. ' LEFT JOIN items i ON h.itemid = i.itemid'. ' WHERE h.itemid='.$this->items[$i]['itemid']. ' AND h.clock>='.$from_time. ' AND h.clock<='.$to_time. ' GROUP BY h.itemid' , 'SELECT hu.itemid, '. ' avg(hu.value) AS avg,min(hu.value) AS min,'. ' max(hu.value) AS max,max(hu.clock) AS clock, max(i.lastvalue) as lst'. ' FROM history_uint hu '. ' LEFT JOIN items i ON hu.itemid = i.itemid'. ' WHERE hu.itemid='.$this->items[$i]['itemid']. ' AND hu.clock>='.$from_time. ' AND hu.clock<='.$to_time. ' GROUP BY hu.itemid' ); } else{ array_push($sql_arr, 'SELECT t.itemid, '. ' avg(t.value_avg) AS avg,min(t.value_min) AS min,'. ' max(t.value_max) AS max,max(t.clock) AS clock, max(i.lastvalue) as lst'. ' FROM trends t '. ' LEFT JOIN items i ON t.itemid = i.itemid'. ' WHERE t.itemid='.$this->items[$i]['itemid']. ' AND t.clock>='.$from_time. ' AND t.clock<='.$to_time. ' GROUP BY t.itemid' , 'SELECT t.itemid, '. ' avg(t.value_avg) AS avg,min(t.value_min) AS min,'. ' max(t.value_max) AS max,max(t.clock) AS clock, max(i.lastvalue) as lst'. ' FROM trends_uint t '. ' LEFT JOIN items i ON t.itemid = i.itemid'. ' WHERE t.itemid='.$this->items[$i]['itemid']. ' AND t.clock>='.$from_time. ' AND t.clock<='.$to_time. ' GROUP BY t.itemid' ); } $curr_data = &$this->data[$this->items[$i]['itemid']][$type]; $curr_data->min = NULL; $curr_data->max = NULL; $curr_data->avg = NULL; $curr_data->clock = NULL; foreach($sql_arr as $sql){ $result=DBselect($sql); while($row=DBfetch($result)){ $curr_data->min = $row['min']; $curr_data->max = $row['max']; $curr_data->avg = $row['avg']; $curr_data->lst = $row['lst']; $curr_data->clock = $row['clock']; $curr_data->shift_min = 0; $curr_data->shift_max = 0; $curr_data->shift_avg = 0; } unset($row); } switch($this->items[$i]['calc_fnc']){ case CALC_FNC_MIN: $item_value = abs($curr_data->min); break; case CALC_FNC_MAX: $item_value = abs($curr_data->max); break; case CALC_FNC_LST: $item_value = abs($curr_data->lst); break; case CALC_FNC_AVG: default: $item_value = abs($curr_data->avg); } if($type == GRAPH_ITEM_SUM){ $this->background = $i; $graph_sum = $item_value; } $this->sum += $item_value; $strvaluelength = max($strvaluelength,strlen(convert_units($item_value,$this->items[$i]['unit']))); } if(isset($graph_sum)) $this->sum = $graph_sum; $this->shiftlegendright += $strvaluelength * 7; } /*function set3DAngle($angle = 70){ if(is_numeric($angle) && ($angle < 85) && ($angle > 10)){ $this->angle3d = (int) $angle; } else { $this->angle3d = 70; } }//*/ function SwitchPie3D($type = false){ if($type){ $this->type = $type; } else{ switch($this->type){ case GRAPH_TYPE_EXPLODED: $this->type = GRAPH_TYPE_3D_EXPLODED; break; case GRAPH_TYPE_3D_EXPLODED: $this->type = GRAPH_TYPE_EXPLODED; break; case GRAPH_TYPE_3D: $this->type = GRAPH_TYPE_PIE; break; case GRAPH_TYPE_PIE: $this->type = GRAPH_TYPE_3D; break; default: $this->type = GRAPH_TYPE_PIE; } } return $this->type; } function SwitchPieExploded($type){ if($type){ $this->type = $type; } else{ switch($this->type){ case GRAPH_TYPE_EXPLODED: $this->type = GRAPH_TYPE_PIE; break; case GRAPH_TYPE_3D_EXPLODED: $this->type = GRAPH_TYPE_3D; break; case GRAPH_TYPE_3D: $this->type = GRAPH_TYPE_3D_EXPLODED; break; case GRAPH_TYPE_PIE: $this->type = GRAPH_TYPE_EXPLODED; break; default: $this->type = GRAPH_TYPE_PIE; } } return $this->type; } function calc3dhight($height){ $this->graphheight3d = (int) ($height/20); } function calcExplodedCenter($anglestart,$angleend,$x,$y,$count){ $count *= $this->exploderad; $anglemid = (int) (($anglestart + $angleend) / 2 ); $y+= round($count * sin(deg2rad($anglemid))); $x+= round($count * cos(deg2rad($anglemid))); return array($x,$y); } function calcExplodedRadius($sizeX,$sizeY,$count){ $count *= $this->exploderad*2; $sizeX -= $count; $sizeY -= $count; return array($sizeX,$sizeY); } function calc3DAngle($sizeX,$sizeY){ $sizeY *= (GRAPH_3D_ANGLE / 90); return array($sizeX,round($sizeY)); } function drawLegend(){ $shiftY = $this->shiftY + $this->shiftYLegend; $max_host_len=0; $max_desc_len=0; for($i=0;$i<$this->num;$i++){ if(strlen($this->items[$i]['host'])>$max_host_len) $max_host_len=strlen($this->items[$i]['host']); if(strlen($this->items[$i]['description'])>$max_desc_len) $max_desc_len=strlen($this->items[$i]['description']); } for($i=0;$i<$this->num;$i++){ $color = $this->GetColor($this->items[$i]['color']); $data = &$this->data[$this->items[$i]['itemid']][$this->items[$i]['calc_type']]; switch($this->items[$i]['calc_fnc']){ case CALC_FNC_MIN: $fnc_name = 'min'; $datavalue = $data->min; break; case CALC_FNC_MAX: $fnc_name = 'max'; $datavalue = $data->max; break; case CALC_FNC_LST: $fnc_name = 'last'; $datavalue = $data->lst; break; case CALC_FNC_AVG: default: $fnc_name = 'avg'; $datavalue = $data->avg; } $proc = ($datavalue * 100)/ $this->sum; // convert_units($datavalue,$this->items[$i]["units"]), if(isset($data) && isset($datavalue)){ $strvalue = sprintf(S_VALUE.': %s ('.((round($proc)!=$proc)?'%0.2f':'%s')."%s)",convert_units($datavalue,$this->items[$i]["units"]),$proc,'%'); $str = sprintf('%s: %s [%s] ', str_pad($this->items[$i]['host'],$max_host_len,' '), str_pad($this->items[$i]['description'],$max_desc_len,' '), $fnc_name); } else{ $strvalue = sprintf(S_VALUE.': '.S_NO_DATA_SMALL); $str=sprintf('%s: %s [ '.S_NO_DATA_SMALL.' ]', str_pad($this->items[$i]['host'],$max_host_len,' '), str_pad($this->items[$i]['description'],$max_desc_len,' ')); } ImageFilledRectangle($this->im,$this->shiftXleft,$this->sizeY+$shiftY+12*$i,$this->shiftXleft+5,$this->sizeY+$shiftY+5+12*$i,$color); ImageRectangle($this->im,$this->shiftXleft,$this->sizeY+$shiftY+12*$i,$this->shiftXleft+5,$this->sizeY+$shiftY+5+12*$i,$this->GetColor('Black No Alpha')); ImageString($this->im, 2, $this->shiftXleft+9, $this->sizeY+$shiftY-5+12*$i, $str, $this->GetColor('Black No Alpha')); $shiftX = $this->fullSizeX - $this->shiftlegendright - $this->shiftXright + 10; // SDI($shiftX.','.$this->sizeX); ImageFilledRectangle($this->im,$shiftX,$this->shiftY+10+5+12*$i,$shiftX+5,$this->shiftY+10+10+12*$i,$color); ImageRectangle($this->im,$shiftX,$this->shiftY+10+5+12*$i,$shiftX+5,$this->shiftY+10+10+12*$i,$this->GetColor('Black No Alpha')); ImageString($this->im, 2, $shiftX+9, $this->shiftY+10+12*$i, $strvalue, $this->GetColor('Black No Alpha')); } if($this->sizeY < 120) return; } function drawElementPie($values){ $sum = $this->sum; if($this->background !== false){ $least = 0; foreach($values as $item => $value){ // SDI($item.' : '.$value.' , '.$this->background); if($item != $this->background){ $least += $value; } } $values[$this->background] -= $least; } if($sum <= 0){ $this->items[0]['color'] = 'FFFFFF'; $values = array(0 => 1); $sum = 1; } // asort($values); $sizeX = $this->sizeX; $sizeY = $this->sizeY; if($this->type == GRAPH_TYPE_EXPLODED){ list($sizeX,$sizeY) = $this->calcExplodedRadius($sizeX,$sizeY,count($values)); } else { $sizeX =(int) $sizeX * 0.95; $sizeY =(int) $sizeY * 0.95; } $xc = $x = (int) $this->sizeX/2 + ($this->shiftXleft); $yc = $y = (int) $this->sizeY/2 + $this->shiftY; $anglestart = 0; $angleend = 0; foreach($values as $item => $value){ $angleend += (int)(360 * $value/$sum)+1; $angleend = ($angleend > 360)?(360):($angleend); if(($angleend - $anglestart) < 1) continue; if($this->type == GRAPH_TYPE_EXPLODED){ list($x,$y) = $this->calcExplodedCenter($anglestart,$angleend,$xc,$yc,count($values)); } imagefilledarc($this->im, $x, $y, $sizeX, $sizeY, $anglestart, $angleend, $this->GetColor($this->items[$item]['color'],0), IMG_ARC_PIE); imagefilledarc($this->im, $x, $y, $sizeX, $sizeY, $anglestart, $angleend, $this->GetColor('Black'), IMG_ARC_PIE|IMG_ARC_EDGED|IMG_ARC_NOFILL); $anglestart = $angleend; } // imageline($this->im, $xc, $yc, $xc, $yc, $this->GetColor('Black')); } function drawElementPie3D($values){ $sum = $this->sum; if($this->background !== false){ $least = 0; foreach($values as $item => $value){ if($item != $this->background){ $least += $value; } } $values[$this->background] -= $least; } if($sum <= 0){ $this->items[0]['color'] = 'FFFFFF'; $values = array(0 => 1); $sum = 1; } // asort($values); $sizeX = $this->sizeX; $sizeY = $this->sizeY; $this->exploderad = $this->exploderad3d; if($this->type == GRAPH_TYPE_3D_EXPLODED){ list($sizeX,$sizeY) = $this->calcExplodedRadius($sizeX,$sizeY,count($values)); } list($sizeX,$sizeY) = $this->calc3DAngle($sizeX,$sizeY); $xc = $x = (int) $this->sizeX/2 + ($this->shiftXleft); $yc = $y = (int) $this->sizeY/2 + $this->shiftY; // ----- bottom angle line ---- $anglestart = 0; $angleend = 0; foreach($values as $item => $value){ $angleend += (int)(360 * $value/$sum)+1; $angleend = ($angleend > 360)?(360):($angleend); if(($angleend - $anglestart) < 1) continue; if($this->type == GRAPH_TYPE_3D_EXPLODED){ list($x,$y) = $this->calcExplodedCenter($anglestart,$angleend,$xc,$yc,count($values)); } imagefilledarc($this->im, $x, $y+$this->graphheight3d+1, $sizeX, $sizeY, $anglestart, $angleend, $this->GetShadow($this->items[$item]['color'],0), IMG_ARC_PIE); imagefilledarc($this->im, $x, $y+$this->graphheight3d+1, $sizeX, $sizeY, $anglestart, $angleend, $this->GetColor('Black'), IMG_ARC_PIE|IMG_ARC_EDGED|IMG_ARC_NOFILL); $anglestart = $angleend; }//*/ // ------ 3d effect ------ for ($i = $this->graphheight3d; $i > 0; $i--) { $anglestart = 0; $angleend = 0; foreach($values as $item => $value){ $angleend += (int)(360 * $value/$sum)+1; $angleend = ($angleend > 360)?(360):($angleend); if(($angleend - $anglestart) < 1) continue; elseif($this->sum == 0) continue; if($this->type == GRAPH_TYPE_3D_EXPLODED){ list($x,$y) = $this->calcExplodedCenter($anglestart,$angleend,$xc,$yc,count($values)); } imagefilledarc($this->im, $x, $y+$i, $sizeX, $sizeY, $anglestart, $angleend, $this->GetShadow($this->items[$item]['color'],0), IMG_ARC_PIE); $anglestart = $angleend; } } $anglestart = 0; $angleend = 0; foreach($values as $item => $value){ $angleend += (int)(360 * $value/$sum)+1; $angleend = ($angleend > 360)?(360):($angleend); if(($angleend - $anglestart) < 1) continue; if($this->type == GRAPH_TYPE_3D_EXPLODED){ list($x,$y) = $this->calcExplodedCenter($anglestart,$angleend,$xc,$yc,count($values)); } imagefilledarc($this->im, $x, $y, $sizeX, $sizeY, $anglestart, $angleend, $this->GetColor($this->items[$item]['color'],0), IMG_ARC_PIE); imagefilledarc($this->im, $x, $y, $sizeX, $sizeY, $anglestart, $angleend, $this->GetColor('Black'), IMG_ARC_PIE|IMG_ARC_EDGED|IMG_ARC_NOFILL); $anglestart = $angleend; }//*/ } function Draw(){ $start_time=getmicrotime(); set_image_header(); check_authorisation(); $this->selectData(); $this->shiftY = 20; $this->shiftYLegend = 20; $this->shiftXleft = 10; $this->shiftXright = 0; $this->fullSizeX = $this->sizeX; $this->fullSizeY = $this->sizeY; if(($this->sizeX < 300) || ($this->sizeY < 200)) $this->switchlegend(0); if($this->drawlegendallow == 1){ $this->sizeX -= ($this->shiftXleft+$this->shiftXright+$this->shiftlegendright); $this->sizeY -= ($this->shiftY+$this->shiftYLegend+12*$this->num+8); } else { $this->sizeX -= ($this->shiftXleft*2); $this->sizeY -= ($this->shiftY*2); } // SDI($this->sizeX.','.$this->sizeY); $this->sizeX = min($this->sizeX,$this->sizeY); $this->sizeY = min($this->sizeX,$this->sizeY); $this->calc3dhight($this->sizeY); $this->exploderad = (int) $this->sizeX / 100; $this->exploderad3d = (int) $this->sizeX / 60; if(function_exists('ImageColorExactAlpha')&&function_exists('ImageCreateTrueColor')&&@imagecreatetruecolor(1,1)) $this->im = imagecreatetruecolor($this->fullSizeX,$this->fullSizeY); else $this->im = imagecreate($this->fullSizeX,$this->fullSizeY); $this->initColors(); $this->drawRectangle(); $this->drawHeader(); $maxX = $this->sizeX; // For each metric for($item = 0; $item < $this->num; $item++){ $minY = $this->m_minY[$this->items[$item]['axisside']]; $maxY = $this->m_maxY[$this->items[$item]['axisside']]; $data = &$this->data[$this->items[$item]['itemid']][$this->items[$item]['calc_type']]; if(!isset($data)) continue; $drawtype = $this->items[$item]['drawtype']; $max_color = $this->GetColor('ValueMax'); $avg_color = $this->GetColor($this->items[$item]['color']); $min_color = $this->GetColor('ValueMin'); $minmax_color = $this->GetColor('ValueMinMax'); $calc_fnc = $this->items[$item]['calc_fnc']; switch($calc_fnc){ case CALC_FNC_MAX: $values[$item] = abs($data->max); break; case CALC_FNC_MIN: $values[$item] = abs($data->min); break; case CALC_FNC_AVG: $values[$item] = abs($data->avg); break; case CALC_FNC_LST: $values[$item] = abs($data->lst); break; } } switch($this->type){ case GRAPH_TYPE_EXPLODED: $this->drawElementPie($values); break; case GRAPH_TYPE_3D: $this->drawElementPie3D($values); break; case GRAPH_TYPE_3D_EXPLODED: $this->drawElementPie3D($values); break; default: $this->drawElementPie($values); break; } $this->drawLogo(); if($this->drawlegendallow == 1) $this->drawLegend(); $end_time=getmicrotime(); $str=sprintf("%0.2f",(getmicrotime()-$start_time)); ImageString($this->im, 0,$this->fullSizeX-120,$this->fullSizeY-12,"Generated in $str sec", $this->GetColor('Gray')); unset($this->items, $this->data); ImageOut($this->im); } } ?>