function mydie($errno, $errstr = '', $errfile = '', $errline = '') { global $conf; $jpgraph = $conf->get_conf('jpgraph_path'); include_once "{$jpgraph}/jpgraph.php"; $err = $errstr ? $errstr : $errno; if ($errfile) { switch ($errno) { case 1: $errprefix = 'Error'; break; case 2: $errprefix = 'Warning'; break; case 8: $errprefix = 'Notice'; break; default: return; // dont show E_STRICT errors } $err = "{$errprefix}: {$err} in '{$errfile}' line {$errline}"; } $error = new JpGraphError(); $error->Raise($err); echo "{$err}"; exit; }
function Stroke(&$img, &$xscale, &$yscale) { $numpoints = count($this->coords[0]) / 2; $img->SetColor($this->color); $img->SetLineWeight($this->weight); if (isset($this->coords[1])) { if (count($this->coords[1]) != $numpoints) { JpGraphError::Raise("Number of X and Y points are not equal. Number of X-points:" . count($this->coords[1]) . " Number of Y-points:{$numpoints}"); } else { $exist_x = true; } } else { $exist_x = false; } if ($exist_x) { $xs = $this->coords[1][0]; } else { $xs = 0; } for ($i = 0; $i < $numpoints; ++$i) { if ($exist_x) { $x = $this->coords[1][$i]; } else { $x = $i; } $xt = $xscale->Translate($x); $yt1 = $yscale->Translate($this->coords[0][$i * 2]); $yt2 = $yscale->Translate($this->coords[0][$i * 2 + 1]); $img->Line($xt, $yt1, $xt, $yt2); $img->Line($xt - $this->errwidth, $yt1, $xt + $this->errwidth, $yt1); $img->Line($xt - $this->errwidth, $yt2, $xt + $this->errwidth, $yt2); } return true; }
function ScatterPlot(&$datay, $datax = false) { if (count($datax) != count($datay) && is_array($datax)) { JpGraphError::Raise("Scatterplot must have equal number of X and Y points."); } $this->Plot($datay, $datax); $this->mark = new PlotMark(); $this->mark->SetType(MARK_CIRCLE); $this->mark->SetColor($this->color); }
function execute() { $this->set_title($this->lang->stats); $this->tree($this->lang->stats); include '../lib/jpgraph/jpgraph.php'; include '../lib/jpgraph/jpgraph_bar.php'; if (!defined('IMG_PNG')) { JpGraphError::Raise("This PHP installation is not configured with PNG support. Please recompile PHP with GD and JPEG support to run JpGraph. (Constant IMG_PNG does not exist)"); } /** * Posts */ $query = $this->db->query("SELECT COUNT(post_id) AS posts, FROM_UNIXTIME(post_time, '%%b %%y') AS month\n\t\t\tFROM %pposts GROUP BY month\tORDER BY post_time"); $data = array(); while ($item = $this->db->nqfetch($query)) { $data[$item['month']] = $item['posts']; } if (!$data) { $data = array(0, 0); } $graph = new Graph(400, 300, 'auto'); $graph->SetScale('textint'); $graph->SetColor('aliceblue'); $graph->SetMarginColor('white'); $graph->xaxis->SetTickLabels(array_keys($data)); $graph->yaxis->scale->SetGrace(20); $graph->title->Set($this->lang->stats_post_by_month); $temp = array_values($data); $barplot = new BarPlot($temp); $barplot->SetFillColor('darkorange'); $graph->add($barplot); $graph->Stroke("../stats/{$this->time}1.png"); /** * Registrations */ $query = $this->db->query("SELECT COUNT(user_id) AS users, FROM_UNIXTIME(user_joined, '%%b %%y') AS month\n\t\t\tFROM %pusers\n\t\t\tWHERE user_joined != 0\n\t\t\tGROUP BY month\n\t\t\tORDER BY user_joined"); $data = array(); while ($item = $this->db->nqfetch($query)) { $data[$item['month']] = $item['users']; } $graph = new Graph(400, 300, 'auto'); $graph->SetScale('textint'); $graph->SetColor('aliceblue'); $graph->SetMarginColor('white'); $graph->xaxis->SetTickLabels(array_keys($data)); $graph->yaxis->scale->SetGrace(20); $graph->title->Set($this->lang->stats_reg_by_month); $temp = array_values($data); $barplot = new BarPlot($temp); $barplot->SetFillColor('darkorange'); $graph->add($barplot); $graph->Stroke("../stats/{$this->time}2.png"); return $this->message($this->lang->stats, "<img src='../stats/{$this->time}1.png' alt='{$this->lang->stats_post_by_month}' /><br /><br />\n\t\t<img src='../stats/{$this->time}2.png' alt='{$this->lang->stats_reg_by_month}' />"); }
function Translate($a) { if ($a < 0) { JpGraphError::Raise("Negative data values can not be used in a log scale."); exit(1); } if ($a == 0) { $a = 1; } $a = log10($a); return floor($this->off + ($a * 1.0 - $this->scale[0]) * $this->scale_factor); }
function Interpolate($xpoint) { $max = $this->n - 1; $min = 0; // Binary search to find interval while ($max - $min > 1) { $k = ($max + $min) / 2; if ($this->xdata[$k] > $xpoint) { $max = $k; } else { $min = $k; } } // Each interval is interpolated by a 3:degree polynom function $h = $this->xdata[$max] - $this->xdata[$min]; if ($h == 0) { JpGraphError::Raise('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.'); } $a = ($this->xdata[$max] - $xpoint) / $h; $b = ($xpoint - $this->xdata[$min]) / $h; return $a * $this->ydata[$min] + $b * $this->ydata[$max] + (($a * $a * $a - $a) * $this->y2[$min] + ($b * $b * $b - $b) * $this->y2[$max]) * ($h * $h) / 6.0; }
function Stroke($aImg) { if ($this->iFile != '' && $this->iCountryFlag != '') { JpGraphError::Raise('It is not possible to specify both an image file and a country flag for the same icon.'); } if ($this->iFile != '') { $gdimg = Graph::LoadBkgImage('', $this->iFile); } else { if (!class_exists('FlagImages')) { JpGraphError::Raise('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.'); } $fobj = new FlagImages($this->iCountryStdSize); $dummy = ''; $gdimg = $fobj->GetImgByName($this->iCountryFlag, $dummy); } if ($this->iX >= 0 && $this->iX <= 1.0) { $w = imagesx($aImg->img); $this->iX = round($w * $this->iX); } if ($this->iY >= 0 && $this->iY <= 1.0) { $h = imagesy($aImg->img); $this->iY = round($h * $this->iY); } $iconw = imagesx($gdimg); $iconh = imagesy($gdimg); if ($this->iHorAnchor == 'center') { $this->iX -= round($iconw * $this->iScale / 2); } if ($this->iHorAnchor == 'right') { $this->iX -= round($iconw * $this->iScale); } if ($this->iVertAnchor == 'center') { $this->iY -= round($iconh * $this->iScale / 2); } if ($this->iVertAnchor == 'bottom') { $this->iY -= round($iconh * $this->iScale); } $aImg->CopyMerge($gdimg, $this->iX, $this->iY, 0, 0, round($iconw * $this->iScale), round($iconh * $this->iScale), $iconw, $iconh, $this->iMix); }
function Stroke($aStrokeFileName = "") { // Set Y-scale if (!$this->yscale->IsSpecified() && count($this->plots) > 0) { list($min, $max) = $this->GetPlotsYMinMax(); $this->yscale->AutoScale($this->img, 0, $max, $this->len / $this->ytick_factor); } // Set start position end length of scale (in absolute pixels) $this->yscale->SetConstants($this->posx, $this->len); // We need as many axis as there are data points $nbrpnts = $this->plots[0]->GetCount(); // If we have no titles just number the axis 1,2,3,... if ($this->axis_title == null) { for ($i = 0; $i < $nbrpnts; ++$i) { $this->axis_title[$i] = $i + 1; } } elseif (count($this->axis_title) < $nbrpnts) { JpGraphError::Raise("JpGraph: Number of titles does not match number of points in plot."); } for ($i = 0; $i < count($this->plots); ++$i) { if ($nbrpnts != $this->plots[$i]->GetCount()) { JpGraphError::Raise("JpGraph: Each spider plot must have the same number of data points."); } } $this->StrokeFrame(); $astep = 2 * M_PI / $nbrpnts; // Prepare legends for ($i = 0; $i < count($this->plots); ++$i) { $this->plots[$i]->Legend($this); } $this->legend->Stroke($this->img); // Plot points $a = M_PI / 2; for ($i = 0; $i < count($this->plots); ++$i) { $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); } // Draw axis and grid for ($i = 0, $a = M_PI / 2; $i < $nbrpnts; ++$i, $a += $astep) { $this->axis->Stroke($this->posy, $a, $grid[$i], $this->axis_title[$i], $i == 0); } $this->grid->Stroke($this->img, $grid); $this->title->Center($this->img->left_margin, $this->img->width - $this->img->right_margin, 5); $this->title->Stroke($this->img); // Stroke texts if ($this->texts != null) { foreach ($this->texts as $t) { $t->Stroke($this->img); } } // Finally output the image $this->cache->PutAndStream($this->img, $this->cache_name, $this->inline, $aStrokeFileName); }
function Stroke($aImg) { // The way the path for the arrow is constructed is partly based // on some heuristics. This is not an exact science but draws the // path in a way that, for me, makes esthetic sence. For example // if the start and end activities are very close we make a small // detour to endter the target horixontally. If there are more // space between axctivities then no suh detour is made and the // target is "hit" directly vertical. I have tried to keep this // simple. no doubt this could become almost infinitive complex // and have some real AI. Feel free to modify this. // This will no-doubt be tweaked as times go by. One design aim // is to avoid having the user choose what types of arrow // he wants. // The arrow is drawn between (x1,y1) to (x2,y2) $x1 = $this->ix1; $x2 = $this->ix2; $y1 = $this->iy1; $y2 = $this->iy2; // Depending on if the target is below or above we have to // handle thi different. if ($y2 > $y1) { $arrowtype = ARROW_DOWN; $midy = round(($y2 - $y1) / 2 + $y1); if ($x2 > $x1) { switch ($this->iPathType) { case 0: $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); break; case 1: case 2: case 3: $c = array($x1, $y1, $x2, $y1, $x2, $y2); break; default: JpGraphError::Raise('Internal error: Unknown path type (=' . $this->iPathType . ') specified for link.'); exit(1); break; } } else { switch ($this->iPathType) { case 0: case 1: $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); break; case 2: // Always extend out horizontally a bit from the first point // If we draw a link back in time (end to start) and the bars // are very close we also change the path so it comes in from // the left on the activity $c = array($x1, $y1, $x1 + $this->iPathExtend, $y1, $x1 + $this->iPathExtend, $midy, $x2, $midy, $x2, $y2); break; case 3: if ($y2 - $midy < 6) { $c = array($x1, $y1, $x1, $midy, $x2 - $this->iPathExtend, $midy, $x2 - $this->iPathExtend, $y2, $x2, $y2); $arrowtype = ARROW_RIGHT; } else { $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); } break; default: JpGraphError::Raise('Internal error: Unknown path type specified for link.'); exit(1); break; } } $arrow = new LinkArrow($x2, $y2, $arrowtype); } else { // Y2 < Y1 $arrowtype = ARROW_UP; $midy = round(($y1 - $y2) / 2 + $y2); if ($x2 > $x1) { switch ($this->iPathType) { case 0: case 1: $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); break; case 3: if ($midy - $y2 < 8) { $arrowtype = ARROW_RIGHT; $c = array($x1, $y1, $x1, $y2, $x2, $y2); } else { $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); } break; default: JpGraphError::Raise('Internal error: Unknown path type specified for link.'); break; } } else { switch ($this->iPathType) { case 0: case 1: $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); break; case 2: // Always extend out horizontally a bit from the first point $c = array($x1, $y1, $x1 + $this->iPathExtend, $y1, $x1 + $this->iPathExtend, $midy, $x2, $midy, $x2, $y2); break; case 3: if ($midy - $y2 < 16) { $arrowtype = ARROW_RIGHT; $c = array($x1, $y1, $x1, $midy, $x2 - $this->iPathExtend, $midy, $x2 - $this->iPathExtend, $y2, $x2, $y2); } else { $c = array($x1, $y1, $x1, $midy, $x2, $midy, $x2, $y2); } break; default: JpGraphError::Raise('Internal error: Unknown path type specified for link.'); exit(1); break; } } $arrow = new LinkArrow($x2, $y2, $arrowtype); } $aImg->SetColor($this->iColor); $aImg->SetLineWeight($this->iWeight); $aImg->Polygon($c); $aImg->SetLineWeight(1); $arrow->SetColor($this->iColor); $arrow->SetSize($this->iArrowSize); $arrow->SetType($this->iArrowType); $arrow->Stroke($aImg); }
function Stroke(&$img, &$xscale, &$yscale) { $numpoints = count($this->coords[0]); if (isset($this->coords[1])) { if (count($this->coords[1]) != $numpoints) { JpGraphError::Raise("Number of X and Y points are not equal. Number of X-points:" . count($this->coords[1]) . " Number of Y-points:{$numpoints}"); } else { $exist_x = true; } } else { $exist_x = false; } if ($exist_x) { $xs = $this->coords[1][0]; } else { $xs = 0; } $img->SetStartPoint($xscale->Translate($xs), $yscale->Translate($this->coords[0][0])); if ($this->filled) { $cord[] = $xscale->Translate($xs); $cord[] = $yscale->Translate($yscale->GetMinVal()); } $xt = $xscale->Translate($xs); $yt = $yscale->Translate($this->coords[0][0]); $cord[] = $xt; $cord[] = $yt; $yt_old = $yt; $this->value->Stroke($img, $this->coords[0][0], $xt, $yt); $img->SetColor($this->color); $img->SetLineWeight($this->weight); $img->SetLineStyle($this->line_style); for ($pnts = 1; $pnts < $numpoints; ++$pnts) { if ($exist_x) { $x = $this->coords[1][$pnts]; } else { $x = $pnts; } $xt = $xscale->Translate($x); $yt = $yscale->Translate($this->coords[0][$pnts]); if ($this->step_style) { $img->StyleLineTo($xt, $yt_old); $img->StyleLineTo($xt, $yt); $cord[] = $xt; $cord[] = $yt_old; $cord[] = $xt; $cord[] = $yt; } else { $cord[] = $xt; $cord[] = $yt; $y = $this->coords[0][$pnts]; if (is_numeric($y) || is_string($y) && $y != "-") { $tmp1 = $this->coords[0][$pnts]; $tmp2 = $this->coords[0][$pnts - 1]; if (is_numeric($tmp1) && (is_numeric($tmp2) || $tmp2 == "-")) { $img->StyleLineTo($xt, $yt); } else { $img->SetStartPoint($xt, $yt); } } } $yt_old = $yt; $this->StrokeDataValue($img, $this->coords[0][$pnts], $xt, $yt); } if ($this->filled) { $cord[] = $xt; $cord[] = $yscale->Translate($yscale->GetMinVal()); $img->SetColor($this->fill_color); $img->FilledPolygon($cord); $img->SetColor($this->color); $img->Polygon($cord); } if (!empty($this->filledAreas)) { $minY = $yscale->Translate($yscale->GetMinVal()); $factor = $this->step_style ? 4 : 2; for ($i = 0; $i < sizeof($this->filledAreas); ++$i) { // go through all filled area elements ordered by insertion // fill polygon array $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor]; $areaCoords[] = $minY; $areaCoords = array_merge($areaCoords, array_slice($cord, $this->filledAreas[$i][0] * $factor, ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor)); $areaCoords[] = $areaCoords[sizeof($areaCoords) - 2]; // last x $areaCoords[] = $minY; // last y if ($this->filledAreas[$i][3]) { $img->SetColor($this->filledAreas[$i][2]); $img->FilledPolygon($areaCoords); $img->SetColor($this->color); } $img->Polygon($areaCoords); $areaCoords = array(); } } $adjust = 0; if ($this->filled) { $adjust = 2; } $factor = 1; if ($this->step_style) { $factor = 2; } $this->csimareas = ""; for ($i = $adjust; $i < count($cord) / $factor - $adjust; $i += 2) { if (is_numeric($this->coords[0][($i - $adjust) / 2])) { $xt = $cord[$i * $factor]; $yt = $cord[$i * $factor + 1]; if (!empty($this->csimtargets[$i])) { $this->mark->SetCSIMTarget($this->csimtargets[$i]); $this->mark->SetCSIMAlt($this->csimalts[$i]); $this->mark->SetCSIMAltVal($this->coords[0][$i]); } $this->mark->Stroke($img, $xt, $yt); $this->csimareas .= $this->mark->GetCSIMAreas(); $this->mark->Stroke($img, $xt, $yt); } } }
function _chkR($aRow) { if (!$this->iInit) { JpGraphError::Raise(27014); // Table not initialized } if ($aRow < 0 || $aRow >= $this->iSize[0]) { JpGraphError::RaiseL(27007, $aRow); } //("GTextTable:\nRow argument ($aRow) is outside specified table size."); }
function Stroke(&$img) { $colors = array_keys($img->rgb->rgb_table); sort($colors); $ta = $this->themearr[$this->theme]; if ($this->setslicecolors == null) { $numcolors = count($ta); } else { $numcolors = count($this->setslicecolors); } // Draw the slices $sum = 0; $n = count($this->data); for ($i = 0; $i < $n; ++$i) { $sum += $this->data[$i]; } // Bail out with error if the sum is 0 if ($sum == 0) { JpGraphError::Raise("Sum of all data is 0 for Pie."); } // Format the titles for each slice for ($i = 0; $i < count($this->data); ++$i) { if ($this->labeltype == 0) { if ($sum != 0) { $l = 100.0 * $this->data[$i] / $sum; } else { $l = 0.0; } } else { $l = $this->data[$i] * 1.0; } if (isset($this->labels[$i]) && is_string($this->labels[$i])) { $this->labels[$i] = sprintf($this->labels[$i], $l); } else { $this->labels[$i] = $l; } } // Set up the pie-circle if ($this->radius < 1) { $this->radius = floor($this->radius * min($img->width, $img->height)); } else { $this->radius = $this->radius; } $xc = round($this->posx * $img->width); $yc = round($this->posy * $img->height); $this->startangle = $this->startangle * M_PI / 180; if ($this->explode_all) { for ($i = 0; $i < count($this->data); ++$i) { $this->explode_radius[$i] = $this->explode_r; } } $n = count($this->data); if ($this->ishadowcolor != "") { $accsum = 0; $angle2 = $this->startangle; $img->SetColor($this->ishadowcolor); for ($i = 0; $sum > 0 && $i < $n; ++$i) { $d = $this->data[$i]; $angle1 = $angle2; $accsum += $d; $angle2 = $this->startangle + 2 * M_PI * $accsum / $sum; if (empty($this->explode_radius[$i])) { $this->explode_radius[$i] = 0; } $la = 2 * M_PI - (abs($angle2 - $angle1) / 2.0 + $angle1); $xcm = $xc + $this->explode_radius[$i] * cos($la); $ycm = $yc - $this->explode_radius[$i] * sin($la); $xcm += $this->ishadowdrop; $ycm += $this->ishadowdrop; $img->CakeSlice($xcm, $ycm, $this->radius, $this->radius, $angle1 * 180 / M_PI, $angle2 * 180 / M_PI, $this->ishadowcolor); } } $accsum = 0; $angle2 = $this->startangle; $img->SetColor($this->color); for ($i = 0; $sum > 0 && $i < $n; ++$i) { $d = $this->data[$i]; $angle1 = $angle2; $accsum += $d; $angle2 = $this->startangle + 2 * M_PI * $accsum / $sum; if ($this->setslicecolors == null) { $slicecolor = $colors[$ta[$i % $numcolors]]; } else { $slicecolor = $this->setslicecolors[$i % $numcolors]; } if ($this->pie_interior_border) { $img->SetColor($this->color); } else { $img->SetColor($slicecolor); } $arccolor = $this->pie_border ? $this->color : ""; $this->la[$i] = 2 * M_PI - (abs($angle2 - $angle1) / 2.0 + $angle1); if (empty($this->explode_radius[$i])) { $this->explode_radius[$i] = 0; } $xcm = $xc + $this->explode_radius[$i] * cos($this->la[$i]); $ycm = $yc - $this->explode_radius[$i] * sin($this->la[$i]); $img->CakeSlice($xcm, $ycm, $this->radius - 1, $this->radius - 1, $angle1 * 180 / M_PI, $angle2 * 180 / M_PI, $slicecolor, $arccolor); if ($this->csimtargets) { $this->AddSliceToCSIM($i, $xcm, $ycm, $this->radius, $angle1, $angle2); } } if ($this->value->show) { $this->StrokeAllLabels($img, $xc, $yc); } // Adjust title position $this->title->Pos($xc, $yc - $this->title->GetFontHeight($img) - $this->radius - $this->title->margin, "center", "bottom"); $this->title->Stroke($img); }
function AutoScale($img, $min, $max, $maxsteps, $majend = true) { if (!is_numeric($min) || !is_numeric($max)) { JpGraphError::Raise(25044); } if ($this->intscale) { $this->IntAutoScale($img, $min, $max, $maxsteps, $majend); return; } if (abs($min - $max) < 1.0E-5) { // We need some difference to be able to autoscale // make it 5% above and 5% below value if ($min == 0 && $max == 0) { // Special case $min = -1; $max = 1; } else { $delta = (abs($max) + abs($min)) * 0.005; $min -= $delta; $max += $delta; } } $gracetop = $this->gracetop / 100.0 * abs($max - $min); $gracebottom = $this->gracebottom / 100.0 * abs($max - $min); if (is_numeric($this->autoscale_min)) { $min = $this->autoscale_min; if ($min >= $max) { JpGraphError::RaiseL(25071); //('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.'); } if (abs($min - $max) < 0.001) { $max *= 1.2; } } if (is_numeric($this->autoscale_max)) { $max = $this->autoscale_max; if ($min >= $max) { JpGraphError::RaiseL(25072); //('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.'); } if (abs($min - $max) < 0.001) { $min *= 0.8; } } $min -= $gracebottom; $max += $gracetop; // First get tickmarks as multiples of 0.1, 1, 10, ... if ($majend) { list($num1steps, $adj1min, $adj1max, $min1step, $maj1step) = $this->CalcTicks($maxsteps, $min, $max, 1, 2); } else { $adj1min = $min; $adj1max = $max; list($num1steps, $min1step, $maj1step) = $this->CalcTicksFreeze($maxsteps, $min, $max, 1, 2, false); } // Then get tick marks as 2:s 0.2, 2, 20, ... if ($majend) { list($num2steps, $adj2min, $adj2max, $min2step, $maj2step) = $this->CalcTicks($maxsteps, $min, $max, 5, 2); } else { $adj2min = $min; $adj2max = $max; list($num2steps, $min2step, $maj2step) = $this->CalcTicksFreeze($maxsteps, $min, $max, 5, 2, false); } // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ... if ($majend) { list($num5steps, $adj5min, $adj5max, $min5step, $maj5step) = $this->CalcTicks($maxsteps, $min, $max, 2, 5); } else { $adj5min = $min; $adj5max = $max; list($num5steps, $min5step, $maj5step) = $this->CalcTicksFreeze($maxsteps, $min, $max, 2, 5, false); } // Check to see whichof 1:s, 2:s or 5:s fit better with // the requested number of major ticks $match1 = abs($num1steps - $maxsteps); $match2 = abs($num2steps - $maxsteps); $match5 = abs($num5steps - $maxsteps); // Compare these three values and see which is the closest match // We use a 0.8 weight to gravitate towards multiple of 5:s $r = $this->MatchMin3($match1, $match2, $match5, 0.8); switch ($r) { case 1: $this->Update($img, $adj1min, $adj1max); $this->ticks->Set($maj1step, $min1step); break; case 2: $this->Update($img, $adj2min, $adj2max); $this->ticks->Set($maj2step, $min2step); break; case 3: $this->Update($img, $adj5min, $adj5max); $this->ticks->Set($maj5step, $min5step); break; } }
function Stroke(&$img, &$xscale, &$yscale) { $numpoints = count($this->coords[0]); if (isset($this->coords[1])) { if (count($this->coords[1]) != $numpoints) { die("JpGraph Error: Number of X and Y points are not equal.<br>\n\t\t\t\t\tNumber of X-points:" . count($this->coords[1]) . "<br>\n\t\t\t\t\tNumber of Y-points:{$numpoints}"); } else { $exist_x = true; } } else { $exist_x = false; } $numbars = count($this->coords[0]); // Use GetMinVal() instead of scale[0] directly since in the case // of log scale we get a correct value. Log scales will have negative // values for values < 1 while still not representing negative numbers. if ($yscale->GetMinVal() >= 0) { $zp = $yscale->scale_abs[0]; } else { $zp = $yscale->Translate(0); } if ($this->abswidth > -1) { $abswidth = $this->abswidth; } else { $abswidth = round($this->width * $xscale->scale_factor, 0); } for ($i = 0; $i < $numbars; $i++) { if ($exist_x) { $x = $this->coords[1][$i]; } else { $x = $i; } $x = $xscale->Translate($x); //if($this->align=="center") //$x -= $abswidth/2; //elseif($this->align=="right") //$x -= $abswidth; if (!$xscale->textscale) { if ($this->align == "center") { $x -= $abswidth / 2; } elseif ($this->align == "right") { $x -= $abswidth; } } $pts = array($x, $zp, $x, $yscale->Translate($this->coords[0][$i]), $x + $abswidth, $yscale->Translate($this->coords[0][$i]), $x + $abswidth, $zp); if ($this->grad) { $grad = new Gradient($img); $grad->FilledRectangle($pts[2], $pts[3], $pts[6], $pts[7], $this->grad_fromcolor, $this->grad_tocolor, $this->grad_style); } elseif (!empty($this->fill_color)) { if (is_array($this->fill_color)) { $img->PushColor($this->fill_color[$i % count($this->fill_color)]); } else { $img->PushColor($this->fill_color); } $img->FilledPolygon($pts); $img->PopColor(); } // Remember value of this bar $val = $this->coords[0][$i]; if ($this->bar_shadow && $val != 0) { $ssh = $this->bar_shadow_hsize; $ssv = $this->bar_shadow_vsize; // Create points to create a "upper-right" shadow if ($val > 0) { $sp[0] = $pts[6]; $sp[1] = $pts[7]; $sp[2] = $pts[4]; $sp[3] = $pts[5]; $sp[4] = $pts[2]; $sp[5] = $pts[3]; $sp[6] = $pts[2] + $ssh; $sp[7] = $pts[3] - $ssv; $sp[8] = $pts[4] + $ssh; $sp[9] = $pts[5] - $ssv; $sp[10] = $pts[6] + $ssh; $sp[11] = $pts[7] - $ssv; } elseif ($val < 0) { $sp[0] = $pts[4]; $sp[1] = $pts[5]; $sp[2] = $pts[6]; $sp[3] = $pts[7]; $sp[4] = $pts[0]; $sp[5] = $pts[1]; $sp[6] = $pts[0] + $ssh; $sp[7] = $pts[1] - $ssv; $sp[8] = $pts[6] + $ssh; $sp[9] = $pts[7] - $ssv; $sp[10] = $pts[4] + $ssh; $sp[11] = $pts[5] - $ssv; } $img->PushColor($this->bar_shadow_color); $img->FilledPolygon($sp); $img->PopColor(); } // Stroke the outline of the bar if (is_array($this->color)) { $img->SetColor($this->color[$i % count($this->color)]); } else { $img->SetColor($this->color); } $img->SetLineWeight($this->weight); $pts[] = $pts[0]; $pts[] = $pts[1]; $img->Polygon($pts); $x = $pts[2] + ($pts[4] - $pts[2]) / 2; if ($this->valuepos == 'top') { $y = $pts[3]; $this->value->Stroke($img, $val, $x, $y); } elseif ($this->valuepos == 'center') { $y = ($pts[3] + $pts[1]) / 2; $this->value->SetAlign('center', 'center'); $this->value->SetMargin(0); $this->value->Stroke($img, $val, $x, $y); } elseif ($this->valuepos == 'bottom') { $y = $pts[1]; $this->value->SetMargin(0); $this->value->Stroke($img, $val, $x, $y); } else { JpGraphError::Raise('Unknown position for values on bars :' . $this->valuepos); die; } // Create the client side image map $rpts = $img->ArrRotate($pts); $csimcoord = round($rpts[0]) . ", " . round($rpts[1]); for ($j = 1; $j < 4; ++$j) { $csimcoord .= ", " . round($rpts[2 * $j]) . ", " . round($rpts[2 * $j + 1]); } $this->csimareas .= '<area shape="poly" coords="' . $csimcoord . '" '; if (!empty($this->csimtargets[$i])) { $this->csimareas .= " href=\"" . $this->csimtargets[$i] . "\""; } if (!empty($this->csimalts[$i])) { $sval = sprintf($this->csimalts[$i], $this->coords[0][$i]); $this->csimareas .= " alt=\"{$sval}\" title=\"{$sval}\" "; } $this->csimareas .= ">\n"; } return true; }
function ScatterPlot($datay, $datax = false) { if (count($datax) != count($datay) && is_array($datax)) { JpGraphError::Raise("Scatterplot must have equal number of X and Y points."); } $this->Plot($datay, $datax); $this->mark = new PlotMark(); $this->mark->SetType(MARK_SQUARE); $this->mark->SetColor($this->color); $this->value->SetAlign('center', 'center'); $this->value->SetMargin(0); }
function Stroke(&$img, $aaoption = 0) { // aaoption is used to handle antialias // aaoption == 0 a normal pie // aaoption == 1 just the body // aaoption == 2 just the values // Explode scaling. If anti anti alias we scale the image // twice and we also need to scale the exploding distance $expscale = $aaoption === 1 ? 2 : 1; if ($this->labeltype == 2) { // Adjust the data so that it will add up to 100% $this->adjusted_data = $this->AdjPercentage($this->data); } $colors = array_keys($img->rgb->rgb_table); sort($colors); $ta = $this->themearr[$this->theme]; $n = count($this->data); if ($this->setslicecolors == null) { $numcolors = count($ta); } else { $this->setslicecolors = array_reverse(array_slice($this->setslicecolors, 0, $n)); $numcolors = count($this->setslicecolors); $tt = array_slice($this->setslicecolors, $n % $numcolors); $tt2 = array_slice($this->setslicecolors, 0, $n % $numcolors); $tt2 = array_merge($tt, $tt2); $this->setslicecolors = $tt + $tt2; } // Draw the slices $sum = 0; for ($i = 0; $i < $n; ++$i) { $sum += $this->data[$i]; } // Bail out with error if the sum is 0 if ($sum == 0) { JpGraphError::Raise("Sum of all data is 0 for Pie."); } // Set up the pie-circle if ($this->radius <= 1) { $radius = floor($this->radius * min($img->width, $img->height)); } else { $radius = $aaoption === 1 ? $this->radius * 2 : $this->radius; } if ($this->posx <= 1 && $this->posx > 0) { $xc = round($this->posx * $img->width); } else { $xc = $this->posx; } if ($this->posy <= 1 && $this->posy > 0) { $yc = round($this->posy * $img->height); } else { $yc = $this->posy; } $n = count($this->data); if ($this->explode_all) { for ($i = 0; $i < $n; ++$i) { $this->explode_radius[$i] = $this->explode_r; } } if ($this->ishadowcolor != "" && $aaoption !== 2) { $accsum = 0; $angle2 = $this->startangle; $img->SetColor($this->ishadowcolor); for ($i = 0; $sum > 0 && $i < $n; ++$i) { $j = $n - $i - 1; $d = $this->data[$i]; $angle1 = $angle2; $accsum += $d; $angle2 = $this->startangle + 2 * M_PI * $accsum / $sum; if (empty($this->explode_radius[$j])) { $this->explode_radius[$j] = 0; } $la = 2 * M_PI - (abs($angle2 - $angle1) / 2.0 + $angle1); $xcm = $xc + $this->explode_radius[$j] * cos($la) * $expscale; $ycm = $yc - $this->explode_radius[$j] * sin($la) * $expscale; $xcm += $this->ishadowdrop * $expscale; $ycm += $this->ishadowdrop * $expscale; $img->CakeSlice($xcm, $ycm, $radius, $radius, $angle1 * 180 / M_PI, $angle2 * 180 / M_PI, $this->ishadowcolor); } } $accsum = 0; $angle2 = $this->startangle; $img->SetColor($this->color); for ($i = 0; $sum > 0 && $i < $n; ++$i) { $j = $n - $i - 1; if (empty($this->explode_radius[$j])) { $this->explode_radius[$j] = 0; } $d = $this->data[$i]; $angle1 = $angle2; $accsum += $d; $angle2 = $this->startangle + 2 * M_PI * $accsum / $sum; $this->la[$i] = 2 * M_PI - (abs($angle2 - $angle1) / 2.0 + $angle1); if ($d == 0) { continue; } if ($this->setslicecolors == null) { $slicecolor = $colors[$ta[$i % $numcolors]]; } else { $slicecolor = $this->setslicecolors[$i % $numcolors]; } if ($this->pie_interior_border && $aaoption === 0) { $img->SetColor($this->color); } else { $img->SetColor($slicecolor); } $arccolor = $this->pie_border && $aaoption === 0 ? $this->color : ""; $xcm = $xc + $this->explode_radius[$j] * cos($this->la[$i]) * $expscale; $ycm = $yc - $this->explode_radius[$j] * sin($this->la[$i]) * $expscale; if ($aaoption !== 2) { $img->CakeSlice($xcm, $ycm, $radius - 1, $radius - 1, $angle1 * 180 / M_PI, $angle2 * 180 / M_PI, $slicecolor, $arccolor); } if ($this->csimtargets && $aaoption !== 1) { $this->AddSliceToCSIM($i, $xcm, $ycm, $radius, $angle1, $angle2); } } // Format the titles for each slice if ($aaoption !== 2) { for ($i = 0; $i < $n; ++$i) { if ($this->labeltype == 0) { if ($sum != 0) { $l = 100.0 * $this->data[$i] / $sum; } else { $l = 0.0; } } elseif ($this->labeltype == 1) { $l = $this->data[$i] * 1.0; } else { $l = $this->adjusted_data[$i]; } if (isset($this->labels[$i]) && is_string($this->labels[$i])) { $this->labels[$i] = sprintf($this->labels[$i], $l); } else { $this->labels[$i] = $l; } } } if ($this->value->show && $aaoption !== 1) { $this->StrokeAllLabels($img, $xc, $yc, $radius); } // Adjust title position if ($aaoption !== 1) { $this->title->Pos($xc, $yc - $this->title->GetFontHeight($img) - $radius - $this->title->margin, "center", "bottom"); $this->title->Stroke($img); } }
function PlotBand($aDir, $aPattern, $aMin, $aMax, $aColor = "black", $aWeight = 1, $aDepth = DEPTH_BACK) { $f = new RectPatternFactory(); $this->prect = $f->Create($aPattern, $aColor, $aWeight); if (is_numeric($aMin) && is_numeric($aMax) && $aMin > $aMax) { JpGraphError::Raise('Min value for plotband is larger than specified max value. Please correct.'); } $this->dir = $aDir; $this->min = $aMin; $this->max = $aMax; $this->depth = $aDepth; }
function AutoScale(&$img, $aStartTime, $aEndTime, $aNumSteps) { assert($aStartTime < $aEndTime); $done = false; $i = 0; while (!$done && $i < 5) { list($adjstart, $adjend, $maj, $min, $format) = $this->DoDateAutoScale($aStartTime, $aEndTime, $i); $n = floor(($adjend - $adjstart) / $maj); if ($n * 1.7 > $aNumSteps) { $done = true; } $i++; } /* if( 0 ) { // DEBUG echo " Start =".date("Y-m-d H:i:s",$aStartTime)."<br>"; echo " End =".date("Y-m-d H:i:s",$aEndTime)."<br>"; echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."<br>"; echo "Adj End =".date("Y-m-d H:i:s",$adjend)."<p>"; echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day<br>"; echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day<br>"; echo "Format=$format<p>"; } */ if ($this->iStartTimeAlign !== false && $this->iStartAlign !== false) { JpGraphError::Raise('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both'); } if ($this->iStartTimeAlign !== false) { if ($this->iStartTimeAlign >= 30) { $adjstart = $this->AdjStartTime($aStartTime, $this->iStartTimeAlign - 30); } elseif ($this->iStartTimeAlign >= 20) { $adjstart = $this->AdjStartTime($aStartTime, false, $this->iStartTimeAlign - 20); } else { $adjstart = $this->AdjStartTime($aStartTime, false, false, $this->iStartTimeAlign); } } if ($this->iEndTimeAlign !== false) { if ($this->iEndTimeAlign >= 30) { $adjend = $this->AdjEndTime($aEndTime, $this->iEndTimeAlign - 30); } elseif ($this->iEndTimeAlign >= 20) { $adjend = $this->AdjEndTime($aEndTime, false, $this->iEndTimeAlign - 20); } else { $adjend = $this->AdjEndTime($aEndTime, false, false, $this->iEndTimeAlign); } } if ($this->iStartAlign !== false) { if ($this->iStartAlign >= 30) { $adjstart = $this->AdjStartDate($aStartTime, $this->iStartAlign - 30); } elseif ($this->iStartAlign >= 20) { $adjstart = $this->AdjStartDate($aStartTime, false, $this->iStartAlign - 20); } else { $adjstart = $this->AdjStartDate($aStartTime, false, false, $this->iStartAlign); } } if ($this->iEndAlign !== false) { if ($this->iEndAlign >= 30) { $adjend = $this->AdjEndDate($aEndTime, $this->iEndAlign - 30); } elseif ($this->iEndAlign >= 20) { $adjend = $this->AdjEndDate($aEndTime, false, $this->iEndAlign - 20); } else { $adjend = $this->AdjEndDate($aEndTime, false, false, $this->iEndAlign); } } $this->Update($img, $adjstart, $adjend); if (!$this->ticks->IsSpecified()) { $this->ticks->Set($maj, $min); } if ($this->date_format == '') { $this->ticks->SetLabelDateFormat($format); } else { $this->ticks->SetLabelDateFormat($this->date_format); } }
function LineErrorPlot(&$datay, $datax = false) { $ly = array(); $ey = array(); $n = count($datay); if ($n % 3 != 0) { JpGraphError::Raise('Error in input data to LineErrorPlot.' . 'Number of data points must be a multiple of 3'); } for ($i = 0; $i < count($datay); $i += 3) { $ly[] = $datay[$i]; $ey[] = $datay[$i] + $datay[$i + 1]; $ey[] = $datay[$i] + $datay[$i + 2]; } $this->ErrorPlot($ey, $datax); $this->line = new LinePlot($ly, $datax); }
public function Stroke($img, $aaoption = 0) { $n = count($this->data); // If user hasn't set the colors use the theme array if ($this->setslicecolors == null) { $colors = array_keys($img->rgb->rgb_table); sort($colors); $idx_a = $this->themearr[$this->theme]; $ca = array(); $m = count($idx_a); for ($i = 0; $i < $m; ++$i) { $ca[$i] = $colors[$idx_a[$i]]; } $ca = array_reverse(array_slice($ca, 0, $n)); } else { $ca = $this->setslicecolors; } if ($this->posx <= 1 && $this->posx > 0) { $xc = round($this->posx * $img->width); } else { $xc = $this->posx; } if ($this->posy <= 1 && $this->posy > 0) { $yc = round($this->posy * $img->height); } else { $yc = $this->posy; } if ($this->radius <= 1) { $width = floor($this->radius * min($img->width, $img->height)); // Make sure that the pie doesn't overflow the image border // The 0.9 factor is simply an extra margin to leave some space // between the pie an the border of the image. $width = min($width, min($xc * 0.9, ($yc * 90 / $this->angle - $width / 4) * 0.9)); } else { $width = $this->radius * ($aaoption === 1 ? 2 : 1); } // Add a sanity check for width if ($width < 1) { JpGraphError::Raise("Width for 3D Pie is 0. Specify a size > 0"); exit; } // Establish a thickness. By default the thickness is a fifth of the // pie slice width (=pie radius) but since the perspective depends // on the inclination angle we use some heuristics to make the edge // slightly thicker the less the angle. // Has user specified an absolute thickness? In that case use // that instead if ($this->iThickness) { $thick = $this->iThickness; $thick *= $aaoption === 1 ? 2 : 1; } else { $thick = $width / 12; } $a = $this->angle; if ($a <= 30) { $thick *= 1.6; } elseif ($a <= 40) { $thick *= 1.4; } elseif ($a <= 50) { $thick *= 1.2; } elseif ($a <= 60) { $thick *= 1.0; } elseif ($a <= 70) { $thick *= 0.8; } elseif ($a <= 80) { $thick *= 0.7; } else { $thick *= 0.6; } $thick = floor($thick); if ($this->explode_all) { for ($i = 0; $i < $n; ++$i) { $this->explode_radius[$i] = $this->explode_r; } } $this->Pie3D($aaoption, $img, $this->data, $ca, $xc, $yc, $width, $this->angle, $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight); // Adjust title position if ($aaoption != 1) { $this->title->Pos($xc, $yc - $this->title->GetFontHeight($img) - $width / 2 - $this->title->margin, "center", "bottom"); $this->title->Stroke($img); } }
function SetTextLabelStart($aStart) { JpGraphError::Raise('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.'); }
function Stroke(&$img, &$xscale, &$yscale) { $numpoints = count($this->coords[0]); if (isset($this->coords[1])) { if (count($this->coords[1]) != $numpoints) { JpGraphError::Raise("Number of X and Y points are not equal. Number of X-points:" . count($this->coords[1]) . " Number of Y-points:{$numpoints}"); } else { $exist_x = true; } } else { $exist_x = false; } if ($this->barcenter) { $textadj = 0.5 - $xscale->text_scale_off; } else { $textadj = 0; } // Find the first numeric data point $startpoint = 0; while ($startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint])) { ++$startpoint; } // Bail out if no data points if ($startpoint == $numpoints) { return; } if ($exist_x) { $xs = $this->coords[1][$startpoint]; } else { $xs = $textadj + $startpoint; } $img->SetStartPoint($xscale->Translate($xs), $yscale->Translate($this->coords[0][$startpoint])); if ($this->filled) { $cord[] = $xscale->Translate($xs); $min = $yscale->GetMinVal(); if ($min > 0 || $this->fillFromMin) { $cord[] = $yscale->Translate($min); } else { $cord[] = $yscale->Translate(0); } } $xt = $xscale->Translate($xs); $yt = $yscale->Translate($this->coords[0][$startpoint]); $cord[] = $xt; $cord[] = $yt; $yt_old = $yt; $this->value->Stroke($img, $this->coords[0][$startpoint], $xt, $yt); $img->SetColor($this->color); $img->SetLineWeight($this->weight); $img->SetLineStyle($this->line_style); for ($pnts = $startpoint + 1; $pnts < $numpoints; ++$pnts) { if ($exist_x) { $x = $this->coords[1][$pnts]; } else { $x = $pnts + $textadj; } $xt = $xscale->Translate($x); $yt = $yscale->Translate($this->coords[0][$pnts]); $y = $this->coords[0][$pnts]; if ($this->step_style && is_numeric($y)) { $img->StyleLineTo($xt, $yt_old); $img->StyleLineTo($xt, $yt); $cord[] = $xt; $cord[] = $yt_old; $cord[] = $xt; $cord[] = $yt; } else { if (is_numeric($y) || is_string($y) && $y != "-") { $tmp1 = $this->coords[0][$pnts]; $tmp2 = $this->coords[0][$pnts - 1]; if (is_numeric($tmp1) && (is_numeric($tmp2) || $tmp2 == "-")) { $img->StyleLineTo($xt, $yt); } else { $img->SetStartPoint($xt, $yt); } if (is_numeric($tmp1) && (is_numeric($tmp2) || $tmp2 == "-" || $this->filled && $tmp2 == '')) { $cord[] = $xt; $cord[] = $yt; } } } $yt_old = $yt; $this->StrokeDataValue($img, $this->coords[0][$pnts], $xt, $yt); } if ($this->filled) { $cord[] = $xt; if ($min > 0 || $this->fillFromMin) { $cord[] = $yscale->Translate($min); } else { $cord[] = $yscale->Translate(0); } if ($this->fillgrad) { $img->SetLineWeight(1); $grad = new Gradient($img); $grad->SetNumColors($this->fillgrad_numcolors); $grad->FilledFlatPolygon($cord, $this->fillgrad_fromcolor, $this->fillgrad_tocolor); $img->SetLineWeight($this->weight); } else { $img->SetColor($this->fill_color); $img->FilledPolygon($cord); } if ($this->line_weight > 0) { $img->SetColor($this->color); $img->Polygon($cord); } } if (!empty($this->filledAreas)) { $minY = $yscale->Translate($yscale->GetMinVal()); $factor = $this->step_style ? 4 : 2; for ($i = 0; $i < sizeof($this->filledAreas); ++$i) { // go through all filled area elements ordered by insertion // fill polygon array $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor]; $areaCoords[] = $minY; $areaCoords = array_merge($areaCoords, array_slice($cord, $this->filledAreas[$i][0] * $factor, ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1)) * $factor)); $areaCoords[] = $areaCoords[sizeof($areaCoords) - 2]; // last x $areaCoords[] = $minY; // last y if ($this->filledAreas[$i][3]) { $img->SetColor($this->filledAreas[$i][2]); $img->FilledPolygon($areaCoords); $img->SetColor($this->color); } // Check if we should draw the frame. // If not we still re-draw the line since it might have been // partially overwritten by the filled area and it doesn't look // very good. // TODO: The behaviour is undefined if the line does not have // any line at the position of the area. if ($this->filledAreas[$i][4]) { $img->Polygon($areaCoords); } else { $img->Polygon($cord); } $areaCoords = array(); } } if ($this->mark->type == -1 || $this->mark->show == false) { return; } for ($pnts = 0; $pnts < $numpoints; ++$pnts) { if ($exist_x) { $x = $this->coords[1][$pnts]; } else { $x = $pnts + $textadj; } $xt = $xscale->Translate($x); $yt = $yscale->Translate($this->coords[0][$pnts]); if (is_numeric($this->coords[0][$pnts])) { if (!empty($this->csimtargets[$pnts])) { $this->mark->SetCSIMTarget($this->csimtargets[$pnts]); $this->mark->SetCSIMAlt($this->csimalts[$pnts]); } if ($exist_x) { $x = $this->coords[1][$pnts]; } else { $x = $pnts; } $this->mark->SetCSIMAltVal($this->coords[0][$pnts], $x); $this->mark->Stroke($img, $xt, $yt); $this->csimareas .= $this->mark->GetCSIMAreas(); $this->StrokeDataValue($img, $this->coords[0][$pnts], $xt, $yt); } } }
function Set($aMajStep, $aMinStep = false) { if ($aMinStep == false) { $aMinStep = $aMajStep; } if ($aMajStep <= 0 || $aMinStep <= 0) { JpGraphError::Raise(" Minor or major step size is 0. Check that you haven't\n\t\t\t\tgot an accidental SetTextTicks(0) in your code.<p>\n\t\t\t\tIf this is not the case you might have stumbled upon a bug in JpGraph.\n\t\t\t\tPlease report this and if possible include the data that caused the\n\t\t\t\tproblem."); } $this->major_step = $aMajStep; $this->minor_step = $aMinStep; $this->is_set = true; }
function Stroke($aStrokeFileName = "") { // Set Y-scale if (!$this->yscale->IsSpecified() && count($this->plots) > 0) { list($min, $max) = $this->GetPlotsYMinMax(); $this->yscale->AutoScale($this->img, 0, $max, $this->len / $this->ytick_factor); } // Set start position end length of scale (in absolute pixels) $this->yscale->SetConstants($this->posx, $this->len); // We need as many axis as there are data points $nbrpnts = $this->plots[0]->GetCount(); // If we have no titles just number the axis 1,2,3,... if ($this->axis_title == null) { for ($i = 0; $i < $nbrpnts; ++$i) { $this->axis_title[$i] = $i + 1; } } elseif (count($this->axis_title) < $nbrpnts) { JpGraphError::Raise("Number of titles does not match number of points in plot."); } for ($i = 0; $i < count($this->plots); ++$i) { if ($nbrpnts != $this->plots[$i]->GetCount()) { JpGraphError::Raise("Each spider plot must have the same number of data points."); } } if ($this->background_image != "") { $this->StrokeFrameBackground(); } else { $this->StrokeFrame(); } $astep = 2 * M_PI / $nbrpnts; // Prepare legends for ($i = 0; $i < count($this->plots); ++$i) { $this->plots[$i]->Legend($this); } $this->legend->Stroke($this->img); $this->footer->Stroke($this->img); if ($this->grid_depth == DEPTH_BACK) { // Draw axis and grid for ($i = 0, $a = M_PI / 2; $i < $nbrpnts; ++$i, $a += $astep) { $this->axis->Stroke($this->posy, $a, $grid[$i], $this->axis_title[$i], $i == 0); } } // Plot points $a = M_PI / 2; for ($i = 0; $i < count($this->plots); ++$i) { $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a); } if ($this->grid_depth != DEPTH_BACK) { // Draw axis and grid for ($i = 0, $a = M_PI / 2; $i < $nbrpnts; ++$i, $a += $astep) { $this->axis->Stroke($this->posy, $a, $grid[$i], $this->axis_title[$i], $i == 0); } } $this->grid->Stroke($this->img, $grid); $this->StrokeTitles(); // Stroke texts if ($this->texts != null) { foreach ($this->texts as $t) { $t->Stroke($this->img); } } // Should we do any final image transformation if ($this->iImgTrans) { if (!class_exists('ImgTrans')) { require_once 'jpgraph_imgtrans.php'; } $tform = new ImgTrans($this->img->img); $this->img->img = $tform->Skew3D($this->iImgTransHorizon, $this->iImgTransSkewDist, $this->iImgTransDirection, $this->iImgTransHighQ, $this->iImgTransMinSize, $this->iImgTransFillColor, $this->iImgTransBorder); } // If the filename is given as the special "__handle" // then the image handler is returned and the image is NOT // streamed back if ($aStrokeFileName == _IMG_HANDLER) { return $this->img->img; } else { // Finally stream the generated picture $this->cache->PutAndStream($this->img, $this->cache_name, $this->inline, $aStrokeFileName); } }
function _TransVert3D($aGdImg, $aHorizon = 100, $aSkewDist = 120, $aDir = SKEW3D_DOWN, $aMinSize = true, $aFillColor = '#FFFFFF', $aQuality = false, $aBorder = false, $aHorizonPos = 0.5) { // Parameter check if ($aHorizonPos < 0 || $aHorizonPos > 1.0) { JpGraphError::Raise("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1."); } $w = imagesx($aGdImg); $h = imagesy($aGdImg); // Create new image $ww = $w; if ($aMinSize) { $hh = ceil($h * $aHorizon / ($aSkewDist + $h)); } else { $hh = $h; } $newgdh = imagecreatetruecolor($ww, $hh); $crgb = new RGB($newgdh); $fillColor = $crgb->Allocate($aFillColor); imagefilledrectangle($newgdh, 0, 0, $ww - 1, $hh - 1, $fillColor); if ($aBorder) { $colidx = $crgb->Allocate($aBorder); imagerectangle($newgdh, 0, 0, $ww - 1, $hh - 1, $colidx); } $mid = round($w * $aHorizonPos); $last = $h; for ($y = 0; $y < $h; ++$y) { $yp = $h - $y - 1; $yt = floor($yp * $aHorizon / ($aSkewDist + $yp)); if (!$aQuality) { if ($last <= $yt) { continue; } $last = $yt; } for ($x = 0; $x < $w; ++$x) { $xt = ($x - $mid) * $aSkewDist / ($aSkewDist + $yp); if ($aDir == SKEW3D_UP) { $rgb = imagecolorat($aGdImg, $x, $h - $y - 1); } else { $rgb = imagecolorat($aGdImg, $x, $y); } $r = $rgb >> 16 & 0xff; $g = $rgb >> 8 & 0xff; $b = $rgb & 0xff; $colidx = imagecolorallocate($newgdh, $r, $g, $b); $xt = round($xt + $mid); if ($aDir == SKEW3D_UP) { $syt = $yt; } else { $syt = $hh - $yt - 1; } if (!empty($set[$yt])) { $nrgb = imagecolorat($newgdh, $xt, $syt); $nr = $nrgb >> 16 & 0xff; $ng = $nrgb >> 8 & 0xff; $nb = $nrgb & 0xff; $colidx = imagecolorallocate($newgdh, floor(($r + $nr) / 2), floor(($g + $ng) / 2), floor(($b + $nb) / 2)); } imagesetpixel($newgdh, $xt, $syt, $colidx); } $set[$yt] = true; } return $newgdh; }
function Stroke($img, $xscale, $yscale) { $n = $this->numpoints; if ($this->center) { $n--; } if (isset($this->coords[1])) { if (count($this->coords[1]) != $n) { JpGraphError::Raise("Number of X and Y points are not equal. Number of X-points:" . count($this->coords[1]) . " Number of Y-points:{$numpoints}"); } else { $exist_x = true; } } else { $exist_x = false; } if ($exist_x) { $xs = $this->coords[1][0]; } else { $xs = 0; } $ts = $this->iTupleSize; $this->csimareas = ''; for ($i = 0; $i < $n; ++$i) { //If value is NULL, then don't draw a bar at all if ($this->coords[0][$i] === null) { continue; } if ($exist_x) { $x = $this->coords[1][$i]; } else { $x = $i; } $xt = $xscale->Translate($x); $neg = $this->coords[0][$i * $ts] > $this->coords[0][$i * $ts + 1]; $yopen = $yscale->Translate($this->coords[0][$i * $ts]); $yclose = $yscale->Translate($this->coords[0][$i * $ts + 1]); $ymin = $yscale->Translate($this->coords[0][$i * $ts + 2]); $ymax = $yscale->Translate($this->coords[0][$i * $ts + 3]); $dx = floor($this->iWidth / 2); $xl = $xt - $dx; $xr = $xt + $dx; if ($neg) { $img->SetColor($this->iStockColor3); } else { $img->SetColor($this->iStockColor1); } $img->FilledRectangle($xl, $yopen, $xr, $yclose); $img->SetLineWeight($this->weight); if ($neg) { $img->SetColor($this->iStockColor2); } else { $img->SetColor($this->color); } $img->Rectangle($xl, $yopen, $xr, $yclose); if ($yopen < $yclose) { $ytop = $yopen; $ybottom = $yclose; } else { $ytop = $yclose; $ybottom = $yopen; } $img->SetColor($this->color); $img->Line($xt, $ytop, $xt, $ymax); $img->Line($xt, $ybottom, $xt, $ymin); if ($this->iEndLines) { $img->Line($xl, $ymax, $xr, $ymax); $img->Line($xl, $ymin, $xr, $ymin); } // A chance for subclasses to add things to the bar // for data point i $this->ModBox($img, $xscale, $yscale, $i, $xl, $xr, $neg); // Setup image maps if (!empty($this->csimtargets[$i])) { $this->csimareas .= '<area shape="rect" coords="' . round($xl) . ',' . round($ytop) . ',' . round($xr) . ',' . round($ybottom) . '" '; $this->csimareas .= ' href="' . $this->csimtargets[$i] . '"'; if (!empty($this->csimalts[$i])) { $sval = $this->csimalts[$i]; $this->csimareas .= " title=\"{$sval}\" "; } $this->csimareas .= " alt=\"{$sval}\" />\n"; } } return true; }
function SetScale($aScale, $rmax = 0) { if ($aScale == 'lin') { $this->scale = new PolarScale($rmax, $this); } elseif ($aScale == 'log') { $this->scale = new PolarLogScale($rmax, $this); } else { JpGraphError::Raise('Unknown scale type for polar graph. Must be "lin" or "log"'); } $this->axis = new PolarAxis($this->img, $this->scale); $this->SetMargin(40, 40, 50, 40); }
function Stroke(&$img, &$xscale, &$yscale) { $pattern = NULL; $img->SetLineWeight($this->weight); for ($i = 0; $i < $this->numpoints - 1; $i++) { $accy = 0; $accy_neg = 0; for ($j = 0; $j < $this->nbrplots; ++$j) { $img->SetColor($this->plots[$j]->color); if ($this->plots[$j]->coords[0][$i] >= 0) { $yt = $yscale->Translate($this->plots[$j]->coords[0][$i] + $accy); $accyt = $yscale->Translate($accy); $accy += $this->plots[$j]->coords[0][$i]; } else { //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) { $yt = $yscale->Translate($this->plots[$j]->coords[0][$i] + $accy_neg); $accyt = $yscale->Translate($accy_neg); $accy_neg += $this->plots[$j]->coords[0][$i]; } $xt = $xscale->Translate($i); if ($this->abswidth > -1) { $abswidth = $this->abswidth; } else { $abswidth = round($this->width * $xscale->scale_factor, 0); } $pts = array($xt, $accyt, $xt, $yt, $xt + $abswidth, $yt, $xt + $abswidth, $accyt); if ($this->bar_shadow) { $ssh = $this->bar_shadow_hsize; $ssv = $this->bar_shadow_vsize; // We must also differ if we are a positive or negative bar. if ($j === 0) { // This gets extra complicated since we have to // see all plots to see if we are negative. It could // for example be that all plots are 0 until the very // last one. We therefore need to save the initial setup // for both the negative and positive case // In case the final bar is positive $sp[0] = $pts[6] + 1; $sp[1] = $pts[7]; $sp[2] = $pts[6] + $ssh; $sp[3] = $pts[7] - $ssv; // In case the final bar is negative $nsp[0] = $pts[0]; $nsp[1] = $pts[1]; $nsp[2] = $pts[0] + $ssh; $nsp[3] = $pts[1] - $ssv; $nsp[4] = $pts[6] + $ssh; $nsp[5] = $pts[7] - $ssv; $nsp[10] = $pts[6] + 1; $nsp[11] = $pts[7]; } if ($j === $this->nbrplots - 1) { // If this is the last plot of the bar and // the total value is larger than 0 then we // add the shadow. if (is_array($this->bar_shadow_color)) { $numcolors = count($this->bar_shadow_color); if ($numcolors == 0) { JpGraphError::Raise('You have specified an empty array for shadow colors in the bar plot.'); } $img->PushColor($this->bar_shadow_color[$i % $numcolors]); } else { $img->PushColor($this->bar_shadow_color); } if ($accy > 0) { $sp[4] = $pts[4] + $ssh; $sp[5] = $pts[5] - $ssv; $sp[6] = $pts[2] + $ssh; $sp[7] = $pts[3] - $ssv; $sp[8] = $pts[2]; $sp[9] = $pts[3] - 1; $sp[10] = $pts[4] + 1; $sp[11] = $pts[5]; $img->FilledPolygon($sp, 4); } elseif ($accy_neg < 0) { $nsp[6] = $pts[4] + $ssh; $nsp[7] = $pts[5] - $ssv; $nsp[8] = $pts[4] + 1; $nsp[9] = $pts[5]; $img->FilledPolygon($nsp, 4); } $img->PopColor(); } } // If value is NULL or 0, then don't draw a bar at all if ($this->plots[$j]->coords[0][$i] == 0) { continue; } if ($this->plots[$j]->grad) { $grad = new Gradient($img); $grad->FilledRectangle($pts[2], $pts[3], $pts[6], $pts[7], $this->plots[$j]->grad_fromcolor, $this->plots[$j]->grad_tocolor, $this->plots[$j]->grad_style); } else { if (is_array($this->plots[$j]->fill_color)) { $numcolors = count($this->plots[$j]->fill_color); $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]); } else { $img->SetColor($this->plots[$j]->fill_color); } $img->FilledPolygon($pts); $img->SetColor($this->plots[$j]->color); } // Stroke the pattern if ($this->plots[$j]->iPattern > -1) { if ($pattern === NULL) { $pattern = new RectPatternFactory(); } $prect = $pattern->Create($this->plots[$j]->iPattern, $this->plots[$j]->iPatternColor, 1); $prect->SetDensity($this->plots[$j]->iPatternDensity); $prect->SetPos(new Rectangle($pts[2], $pts[3], $pts[4] - $pts[0] + 1, $pts[1] - $pts[3] + 1)); $prect->Stroke($img); } // CSIM array if ($i < count($this->plots[$j]->csimtargets)) { // Create the client side image map $rpts = $img->ArrRotate($pts); $csimcoord = round($rpts[0]) . ", " . round($rpts[1]); for ($k = 1; $k < 4; ++$k) { $csimcoord .= ", " . round($rpts[2 * $k]) . ", " . round($rpts[2 * $k + 1]); } if (!empty($this->plots[$j]->csimtargets[$i])) { $this->csimareas .= '<area shape="poly" coords="' . $csimcoord . '" '; $this->csimareas .= " href=\"" . $this->plots[$j]->csimtargets[$i] . "\""; if (!empty($this->plots[$j]->csimalts[$i])) { $sval = sprintf($this->plots[$j]->csimalts[$i], $this->plots[$j]->coords[0][$i]); $this->csimareas .= " alt=\"{$sval}\" title=\"{$sval}\" "; } $this->csimareas .= ">\n"; } } $pts[] = $pts[0]; $pts[] = $pts[1]; $img->Polygon($pts); } // Draw labels for each acc.bar $x = $pts[2] + ($pts[4] - $pts[2]) / 2; $y = $yscale->Translate($accy); if ($this->bar_shadow) { $x += $ssh; } $this->value->Stroke($img, $accy, $x, $y); $accy = 0; $accy_neg = 0; for ($j = 0; $j < $this->nbrplots; ++$j) { // We don't print 0 values in an accumulated bar plot if ($this->plots[$j]->coords[0][$i] == 0) { continue; } if ($this->plots[$j]->coords[0][$i] > 0) { $yt = $yscale->Translate($this->plots[$j]->coords[0][$i] + $accy); $accyt = $yscale->Translate($accy); $y = $accyt - ($accyt - $yt) / 2; $accy += $this->plots[$j]->coords[0][$i]; } else { $yt = $yscale->Translate($this->plots[$j]->coords[0][$i] + $accy_neg); $accyt = $yscale->Translate($accy_neg); //$y=0; $accy_neg += $this->plots[$j]->coords[0][$i]; $y = $accyt - ($accyt - $yt) / 2; // TODO : Check this fix } $this->plots[$j]->value->SetAlign("center", "center"); $this->plots[$j]->value->SetMargin(0); $this->plots[$j]->value->Stroke($img, $this->plots[$j]->coords[0][$i], $x, $y); } } return true; }
function Stroke(&$aImg, &$aXScale, &$aYScale) { $aImg->SetColor($this->color); $aImg->SetLineWeight($this->weight); if ($this->direction == VERTICAL) { $ymin_abs = $aYScale->Translate($aYScale->GetMinVal()); $ymax_abs = $aYScale->Translate($aYScale->GetMaxVal()); $xpos_abs = $aXScale->Translate($this->scaleposition); $aImg->Line($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs); } elseif ($this->direction == HORIZONTAL) { $xmin_abs = $aXScale->Translate($aXScale->GetMinVal()); $xmax_abs = $aXScale->Translate($aXScale->GetMaxVal()); $ypos_abs = $aYScale->Translate($this->scaleposition); $aImg->Line($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs); } else { JpGraphError::Raise(" Illegal direction for static line"); } }
function GetIdxByName($aName, &$outFullName) { if (is_integer($aName)) { $idx = $this->GetIdxByOrdinal($aName, $outFullName); return $idx; } $found = false; $aName = strtolower($aName); $nlen = strlen($aName); reset($this->iCountryNameMap); // Match partial full country name or exact idx name while (list($key, $val) = each($this->iCountryNameMap)) { if (strpos(strtolower($key), $aName) !== false || $nlen == strlen($val) && $val == $aName) { $found = true; break; } } if ($found) { $outFullName = $key; return $val; } else { JpGraphError::Raise("The (partial) country name \"{$aName}\" does not have a cooresponding flag image. The flag may still exist but under another name, e.g. insted of \"usa\" try \"united states\"."); } }