forked from Wavyzz/dolibarr
2617 lines
80 KiB
PHP
2617 lines
80 KiB
PHP
<?php
|
|
/*
|
|
Copyright (C) 1998, 1999, 2000, 2001 Afan Ottenheimer. Released under
|
|
the GPL and PHP licenses as stated in the the README file which
|
|
should have been included with this document.
|
|
|
|
World Coordinates are the XY coordinates relative to the
|
|
axis origin that can be drawn. Not the device (pixel) coordinates
|
|
which in GD is relative to the origin at the upper left
|
|
side of the image.
|
|
*/
|
|
|
|
//PHPLOT Version 4.4.6
|
|
//Requires PHP 3.0.2 or later
|
|
|
|
|
|
class PHPlot{
|
|
|
|
var $is_inline = 0; //0 = Sends headers, 1 = sends just raw image data
|
|
var $browser_cache = '1'; // 0 = Sends headers for browser to not cache the image, (i.e. 0 = don't let browser cache image)
|
|
// (only if is_inline = 0 also)
|
|
var $session_set = ''; //Do not change
|
|
var $scale_is_set = ''; //Do not change
|
|
var $draw_plot_area_background = '';
|
|
|
|
var $image_width; //Total Width in Pixels
|
|
var $image_height; //Total Height in Pixels
|
|
var $image_border_type = ''; //raised, plain, ''
|
|
var $x_left_margin;
|
|
var $y_top_margin;
|
|
var $x_right_margin;
|
|
var $y_bot_margin;
|
|
var $plot_area = array(5,5,600,400);
|
|
var $x_axis_position = 0; //Where to draw the X_axis (world coordinates)
|
|
var $y_axis_position = ''; //Leave blank for Y axis at left of plot. (world coord.)
|
|
var $xscale_type = 'linear'; //linear or log
|
|
var $yscale_type = 'linear';
|
|
|
|
//Use for multiple plots per image
|
|
var $print_image = 1; //Used for multiple charts per image.
|
|
|
|
//Fonts
|
|
var $use_ttf = 0; //Use TTF fonts (1) or not (0)
|
|
var $font_path = './'; //To be added
|
|
var $font = './benjamingothic.ttf';
|
|
|
|
///////////Fonts: Small/Generic
|
|
var $small_ttffont_size = 12; //
|
|
//non-ttf
|
|
var $small_font = 2; // fonts = 1,2,3,4 or 5
|
|
var $small_font_width = 6.0; // width in pixels (2=6,3=8,4=8)
|
|
var $small_font_height = 8.0; // height in pixels (2=8,3=10,4=12)
|
|
|
|
////////// Fonts:Title
|
|
var $title_ttffont = './benjamingothic.ttf';
|
|
var $title_ttffont_size = 14;
|
|
var $title_angle= 0;
|
|
//non-ttf
|
|
var $title_font = '4'; // fonts = 1,2,3,4,5
|
|
|
|
////////////// Fonts:Axis
|
|
var $axis_ttffont = './benjamingothic.ttf';
|
|
var $axis_ttffont_size = 8;
|
|
var $x_datalabel_angle = 0;
|
|
//non-ttf
|
|
var $axis_font = 2;
|
|
|
|
////////////////Fonts:Labels of Data
|
|
var $datalabel_font = '2';
|
|
|
|
//////////////// Fonts:Labels (Axis Titles)
|
|
var $x_label_ttffont = './benjamingothic.ttf';
|
|
var $x_label_ttffont_size = '12';
|
|
var $x_label_angle = '0';
|
|
|
|
var $y_label_ttffont = './benjamingothic.ttf';
|
|
var $y_label_ttffont_size = '12';
|
|
var $y_label_angle = 90;
|
|
var $y_label_width = '';
|
|
|
|
//Formats
|
|
var $file_format = 'png';
|
|
var $file_name = ''; //For output to a file instead of stdout
|
|
|
|
//Plot Colors
|
|
var $shading = 0;
|
|
var $color_array = 1; //1 = include small list
|
|
//2 = include large list
|
|
//array = define your own color translation. See rgb.inc.php and SetRGBArray
|
|
var $bg_color;
|
|
var $plot_bg_color;
|
|
var $grid_color;
|
|
var $light_grid_color;
|
|
var $tick_color;
|
|
var $title_color;
|
|
var $label_color;
|
|
var $text_color;
|
|
var $i_light = '';
|
|
|
|
//Data
|
|
var $data_type = 'text-data'; //text-data, data-data-error, data-data
|
|
var $plot_type= 'linepoints'; //bars, lines, linepoints, area, points, pie, thinbarline
|
|
var $line_width = 2;
|
|
var $line_style = array('solid','solid','solid','dashed','dashed','solid'); //Solid or dashed lines
|
|
|
|
var $data_color = ''; //array('blue','green','yellow',array(0,0,0));
|
|
var $data_border_color = '';
|
|
|
|
var $label_scale_position = '.5'; //1 = top, 0 = bottom
|
|
var $group_frac_width = '.7'; //value from 0 to 1 = width of bar
|
|
var $bar_width_adjust = '1'; //1 = bars of normal width, must be > 0
|
|
|
|
var $point_size = 10;
|
|
var $point_shape = 'diamond'; //rect,circle,diamond,triangle,dot,line,halfline
|
|
var $error_bar_shape = 'tee'; //tee, line
|
|
var $error_bar_size = 5; //right left size of tee
|
|
var $error_bar_line_width = ''; //If set then use it, else use $line_width for thickness
|
|
var $error_bar_color = '';
|
|
var $data_values;
|
|
|
|
var $plot_border_type = 'full'; //left, none, full
|
|
var $plot_area_width = '';
|
|
var $number_x_points;
|
|
var $plot_min_x; // Max and min of the plot area
|
|
var $plot_max_x= ''; // Max and min of the plot area
|
|
var $plot_min_y= ''; // Max and min of the plot area
|
|
var $plot_max_y = ''; // Max and min of the plot area
|
|
var $min_y = '';
|
|
var $max_y = '';
|
|
var $max_x = 10; //Must not be = 0;
|
|
var $y_precision = '1';
|
|
var $x_precision = '1';
|
|
var $si_units = '';
|
|
|
|
//Labels
|
|
var $draw_data_labels = '0';
|
|
var $legend = ''; //an array
|
|
var $legend_x_pos = '';
|
|
var $legend_y_pos = '';
|
|
var $title_txt = "";
|
|
var $y_label_txt = '';
|
|
var $x_label_txt = "";
|
|
|
|
//DataAxis Labels (on each axis)
|
|
var $y_grid_label_type = 'data'; //data, none, time, other
|
|
var $y_grid_label_pos = 'plotleft'; //plotleft, plotright, yaxis, both
|
|
var $x_grid_label_type = 'data'; //data, title, none, time, other
|
|
var $draw_x_data_labels = ''; // 0=false, 1=true, ""=let program decide
|
|
var $x_time_format = "%H:%m:%s"; //See http://www.php.net/manual/html/function.strftime.html
|
|
var $x_datalabel_maxlength = 10;
|
|
|
|
//Tick Formatting
|
|
var $tick_length = '10'; //pixels: tick length from axis left/downward
|
|
//tick_length2 to be implemented
|
|
//var $tick_length2 = ''; //pixels: tick length from axis line rightward/upward
|
|
var $draw_vert_ticks = 1; //1 = draw ticks, 0 = don't draw ticks
|
|
var $num_vert_ticks = '';
|
|
var $vert_tick_increment=''; //Set num_vert_ticks or vert_tick_increment, not both.
|
|
var $vert_tick_position = 'both'; //plotright=(right of plot only), plotleft=(left of plot only),
|
|
//both = (both left and right of plot), yaxis=(crosses y axis)
|
|
var $horiz_tick_increment=''; //Set num_horiz_ticks or horiz_tick_increment, not both.
|
|
var $num_horiz_ticks='';
|
|
var $skip_top_tick = '0';
|
|
var $skip_bottom_tick = '0';
|
|
|
|
//Grid Formatting
|
|
var $draw_x_grid = 0;
|
|
var $draw_y_grid = 1;
|
|
|
|
|
|
//BEGIN CODE
|
|
//////////////////////////////////////////////////////
|
|
//Constructor: Setup Img pointer, Colors and Size of Image
|
|
function PHPlot($which_width=600,$which_height=400,$which_output_file="",$which_input_file="") {
|
|
|
|
$this->SetRGBArray('2');
|
|
$this->background_done = 0; //Set to 1 after background image first drawn
|
|
|
|
if ($which_output_file != "") { $this->SetOutputFile($which_output_file); };
|
|
|
|
if ($which_input_file != "") {
|
|
$this->SetInputFile($which_input_file) ;
|
|
} else {
|
|
$this->SetImageArea($which_width, $which_height);
|
|
$this->InitImage();
|
|
}
|
|
|
|
if ( ($this->session_set == 1) && ($this->img == "") ) { //For sessions
|
|
//Do nothing
|
|
} else {
|
|
$this->SetDefaultColors();
|
|
}
|
|
|
|
$this->SetIndexColors();
|
|
|
|
}
|
|
|
|
//Set up the image and colors
|
|
function InitImage() {
|
|
//if ($this->img) {
|
|
// ImageDestroy($this->img);
|
|
//}
|
|
$this->img = ImageCreate($this->image_width, $this->image_height);
|
|
return true;
|
|
}
|
|
|
|
function SetBrowserCache($which_browser_cache) { //Submitted by Thiemo Nagel
|
|
$this->browser_cache = $which_browser_cache;
|
|
return true;
|
|
}
|
|
|
|
function SetPrintImage($which_pi) {
|
|
$this->print_image = $which_pi;
|
|
return true;
|
|
}
|
|
|
|
function SetIsInline($which_ii) {
|
|
$this->is_inline = $which_ii;
|
|
return true;
|
|
}
|
|
|
|
function SetUseTTF($which_ttf) {
|
|
$this->use_ttf = $which_ttf;
|
|
return true;
|
|
}
|
|
|
|
function SetTitleFontSize($which_tfs) {
|
|
//TTF
|
|
$this->title_ttffont_size = $which_tfs; //pt size
|
|
|
|
//Non-TTF settings
|
|
if (($which_tfs > 5) && (!$this->use_ttf)) {
|
|
$this->DrawError('Non-TTF font size must be 1,2,3,4 or 5');
|
|
return false;
|
|
} else {
|
|
$this->title_font = $which_tfs;
|
|
//$this->title_font_height = ImageFontHeight($which_tfs) // height in pixels
|
|
//$this->title_font_width = ImageFontWidth($which_tfs); // width in pixels
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetLineStyles($which_sls){
|
|
$this->line_style = $which_sls;
|
|
return true;
|
|
}
|
|
|
|
function SetLegend($which_leg){
|
|
if (is_array($which_leg)) {
|
|
$this->legend = $which_leg;
|
|
return true;
|
|
} else {
|
|
$this->DrawError('Error: SetLegend argument must be an array');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function SetLegendPixels($which_x,$which_y,$which_type) {
|
|
//which_type not yet used
|
|
$this->legend_x_pos = $which_x;
|
|
$this->legend_y_pos = $which_y;
|
|
return true;
|
|
}
|
|
|
|
function SetLegendWorld($which_x,$which_y,$which_type='') {
|
|
//which_type not yet used
|
|
//Must be called after scales are set up.
|
|
if ($this->scale_is_set != 1) { $this->SetTranslation(); };
|
|
$this->legend_x_pos = $this->xtr($which_x);
|
|
$this->legend_y_pos = $this->ytr($which_y);
|
|
return true;
|
|
}
|
|
|
|
function SetFileFormat($which_file_format) {
|
|
//eventually test to see if that is supported - if not then return false
|
|
$asked = strtolower(trim($which_file_format));
|
|
if( ($asked=='jpg') || ($asked=='png') || ($asked=='gif') || ($asked=='wbmp') ) {
|
|
$this->file_format = $asked;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function SetInputFile($which_input_file) {
|
|
//$this->SetFileFormat($which_frmt);
|
|
$size = GetImageSize($which_input_file);
|
|
$input_type = $size[2];
|
|
|
|
switch($input_type) { //After SetFileFormat is in lower case
|
|
case "1":
|
|
$im = @ImageCreateFromGIF ($which_input_file);
|
|
if (!$im) { // See if it failed
|
|
$this->PrintError("Unable to open $which_input_file as a GIF");
|
|
return false;
|
|
}
|
|
break;
|
|
case "3":
|
|
$im = @ImageCreateFromPNG ($which_input_file);
|
|
if (!$im) { // See if it failed
|
|
$this->PrintError("Unable to open $which_input_file as a PNG");
|
|
return false;
|
|
}
|
|
break;
|
|
case "2":
|
|
$im = @ImageCreateFromJPEG ($which_input_file);
|
|
if (!$im) { // See if it failed
|
|
$this->PrintError("Unable to open $which_input_file as a JPG");
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
$this->PrintError('Please select wbmp,gif,jpg, or png for image type!');
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
//Get Width and Height of Image
|
|
$this->SetImageArea($size[0],$size[1]);
|
|
|
|
$this->img = $im;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
function SetOutputFile($which_output_file) {
|
|
$this->output_file = $which_output_file;
|
|
return true;
|
|
}
|
|
|
|
function SetImageArea($which_iw,$which_ih) {
|
|
//Note this is now an Internal function - please set w/h via PHPlot()
|
|
$this->image_width = $which_iw;
|
|
$this->image_height = $which_ih;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
function SetYAxisPosition($which_pos) {
|
|
$this->y_axis_position = $which_pos;
|
|
return true;
|
|
}
|
|
function SetXAxisPosition($which_pos) {
|
|
$this->x_axis_position = $which_pos;
|
|
return true;
|
|
}
|
|
function SetXTimeFormat($which_xtf) {
|
|
$this->x_time_format = $which_xtf;
|
|
return true;
|
|
}
|
|
function SetXDataLabelMaxlength($which_xdlm) {
|
|
if ($which_xdlm >0 ) {
|
|
$this->x_datalabel_maxlength = $which_xdlm;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
function SetXDataLabelAngle($which_xdla) {
|
|
$this->x_datalabel_angle = $which_xdla;
|
|
return true;
|
|
}
|
|
function SetXScaleType($which_xst) {
|
|
$this->xscale_type = $which_xst;
|
|
return true;
|
|
}
|
|
function SetYScaleType($which_yst) {
|
|
$this->yscale_type = $which_yst;
|
|
if ($this->x_axis_position <= 0) {
|
|
$this->x_axis_position = 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetPrecisionX($which_prec) {
|
|
$this->x_precision = $which_prec;
|
|
return true;
|
|
}
|
|
function SetPrecisionY($which_prec) {
|
|
$this->y_precision = $which_prec;
|
|
return true;
|
|
}
|
|
|
|
|
|
function SetIndexColors() { //Internal Method called to set colors and preserve state
|
|
//These are the colors of the image that are used. They are initialized
|
|
//to work with sessions and PHP.
|
|
|
|
$this->ndx_i_light = $this->SetIndexColor($this->i_light);
|
|
$this->ndx_i_dark = $this->SetIndexColor($this->i_dark);
|
|
$this->ndx_bg_color= $this->SetIndexColor($this->bg_color);
|
|
$this->ndx_plot_bg_color= $this->SetIndexColor($this->plot_bg_color);
|
|
|
|
$this->ndx_title_color= $this->SetIndexColor($this->title_color);
|
|
$this->ndx_tick_color= $this->SetIndexColor($this->tick_color);
|
|
$this->ndx_label_color= $this->SetIndexColor($this->label_color);
|
|
$this->ndx_text_color= $this->SetIndexColor($this->text_color);
|
|
$this->ndx_light_grid_color= $this->SetIndexColor($this->light_grid_color);
|
|
$this->ndx_grid_color= $this->SetIndexColor($this->grid_color);
|
|
|
|
reset($this->error_bar_color);
|
|
unset($ndx_error_bar_color);
|
|
$i = 0;
|
|
while (list(, $col) = each($this->error_bar_color)) {
|
|
$this->ndx_error_bar_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
//reset($this->data_border_color);
|
|
unset($ndx_data_border_color);
|
|
$i = 0;
|
|
while (list(, $col) = each($this->data_border_color)) {
|
|
$this->ndx_data_border_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
//reset($this->data_color);
|
|
unset($ndx_data_color);
|
|
$i = 0;
|
|
while (list(, $col) = each($this->data_color)) {
|
|
$this->ndx_data_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
function SetDefaultColors() {
|
|
|
|
$this->i_light = array(194,194,194);
|
|
$this->i_dark = array(100,100,100);
|
|
$this->SetPlotBgColor(array(222,222,222));
|
|
$this->SetBackgroundColor(array(200,222,222)); //can use rgb values or "name" values
|
|
$this->SetLabelColor('black');
|
|
$this->SetTextColor('black');
|
|
$this->SetGridColor('black');
|
|
$this->SetLightGridColor(array(175,175,175));
|
|
$this->SetTickColor('black');
|
|
$this->SetTitleColor(array(0,0,0)); // Can be array or name
|
|
$this->data_color = array('blue','green','yellow','red','orange');
|
|
$this->error_bar_color = array('blue','green','yellow','red','orange');
|
|
$this->data_border_color = array('black');
|
|
|
|
$this->session_set = 1; //Mark it down for PHP session() usage.
|
|
}
|
|
|
|
function PrintImage() {
|
|
|
|
if ( ($this->browser_cache == 0) && ($this->is_inline == 0)) { //Submitted by Thiemo Nagel
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
|
header('Last-Modified: ' . gmdate("D, d M Y H:i:s") . 'GMT');
|
|
header('Cache-Control: no-cache, must-revalidate');
|
|
header('Pragma: no-cache');
|
|
}
|
|
|
|
switch($this->file_format) {
|
|
case "png":
|
|
if ($this->is_inline == 0) {
|
|
Header('Content-type: image/png');
|
|
}
|
|
if ($this->is_inline == 1 && $this->output_file != "") {
|
|
ImagePng($this->img,$this->output_file);
|
|
} else {
|
|
ImagePng($this->img);
|
|
}
|
|
break;
|
|
case "jpg":
|
|
if ($this->is_inline == 0) {
|
|
Header('Content-type: image/jpeg');
|
|
}
|
|
if ($this->is_inline == 1 && $this->output_file != "") {
|
|
ImageJPEG($this->img,$this->output_file);
|
|
} else {
|
|
ImageJPEG($this->img);
|
|
}
|
|
break;
|
|
case "gif":
|
|
if ($this->is_inline == 0) {
|
|
Header('Content-type: image/gif');
|
|
}
|
|
if ($this->is_inline == 1 && $this->output_file != "") {
|
|
ImageGIF($this->img,$this->output_file);
|
|
} else {
|
|
ImageGIF($this->img);
|
|
}
|
|
|
|
break;
|
|
case "wbmp":
|
|
if ($this->is_inline == 0) {
|
|
Header('Content-type: image/wbmp');
|
|
}
|
|
if ($this->is_inline == 1 && $this->output_file != "") {
|
|
ImageWBMP($this->img,$this->output_file);
|
|
} else {
|
|
ImageWBMP($this->img);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
$this->PrintError('Please select an image type!<br>');
|
|
break;
|
|
}
|
|
ImageDestroy($this->img);
|
|
return true;
|
|
}
|
|
|
|
|
|
function DrawBackground() {
|
|
//if ($this->img == "") { $this->InitImage(); };
|
|
if ($this->background_done == 0) { //Don't draw it twice if drawing two plots on one image
|
|
ImageFilledRectangle($this->img, 0, 0,
|
|
$this->image_width, $this->image_height, $this->ndx_bg_color);
|
|
$this->background_done = 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawImageBorder() {
|
|
switch ($this->image_border_type) {
|
|
case "raised":
|
|
ImageLine($this->img,0,0,$this->image_width-1,0,$this->ndx_i_light);
|
|
ImageLine($this->img,1,1,$this->image_width-2,1,$this->ndx_i_light);
|
|
ImageLine($this->img,0,0,0,$this->image_height-1,$this->ndx_i_light);
|
|
ImageLine($this->img,1,1,1,$this->image_height-2,$this->ndx_i_light);
|
|
ImageLine($this->img,$this->image_width-1,0,$this->image_width-1,$this->image_height-1,$this->ndx_i_dark);
|
|
ImageLine($this->img,0,$this->image_height-1,$this->image_width-1,$this->image_height-1,$this->ndx_i_dark);
|
|
ImageLine($this->img,$this->image_width-2,1,$this->image_width-2,$this->image_height-2,$this->ndx_i_dark);
|
|
ImageLine($this->img,1,$this->image_height-2,$this->image_width-2,$this->image_height-2,$this->ndx_i_dark);
|
|
break;
|
|
case "plain":
|
|
ImageLine($this->img,0,0,$this->image_width,0,$this->ndx_i_dark);
|
|
ImageLine($this->img,$this->image_width-1,0,$this->image_width-1,$this->image_height,$this->ndx_i_dark);
|
|
ImageLine($this->img,$this->image_width-1,$this->image_height-1,0,$this->image_height-1,$this->ndx_i_dark);
|
|
ImageLine($this->img,0,0,0,$this->image_height,$this->ndx_i_dark);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetPlotBorderType($which_pbt) {
|
|
$this->plot_border_type = $which_pbt; //left, none, anything else=full
|
|
}
|
|
|
|
function SetImageBorderType($which_sibt) {
|
|
$this->image_border_type = $which_sibt; //raised, plain
|
|
}
|
|
|
|
function SetDrawPlotAreaBackground($which_dpab) {
|
|
$this->draw_plot_area_background = $which_dpab; // 1=true or anything else=false
|
|
}
|
|
|
|
function SetDrawDataLabels($which_ddl) { //Draw next to datapoints
|
|
$this->draw_data_labels = $which_ddl; // 1=true or anything else=false
|
|
}
|
|
|
|
function SetDrawXDataLabels($which_dxdl) { //Draw on X Axis
|
|
$this->draw_x_data_labels = $which_dxdl; // 1=true or anything else=false
|
|
}
|
|
|
|
function SetDrawYGrid($which_dyg) {
|
|
$this->draw_y_grid = $which_dyg; // 1=true or anything else=false
|
|
}
|
|
|
|
function SetDrawXGrid($which_dxg) {
|
|
$this->draw_x_grid = $which_dxg; // 1=true or anything else=false
|
|
}
|
|
|
|
function SetYGridLabelType($which_yglt) {
|
|
$this->y_grid_label_type = $which_yglt;
|
|
return true;
|
|
}
|
|
|
|
function SetXGridLabelType($which_xglt) {
|
|
$this->x_grid_label_type = $which_xglt;
|
|
return true;
|
|
}
|
|
|
|
function SetXLabel($xlbl) {
|
|
$this->x_label_txt = $xlbl;
|
|
return true;
|
|
}
|
|
function SetYLabel($ylbl) {
|
|
$this->y_label_txt = $ylbl;
|
|
return true;
|
|
}
|
|
function SetTitle($title) {
|
|
$this->title_txt = $title;
|
|
return true;
|
|
}
|
|
function DrawLabels() {
|
|
$this->DrawTitle();
|
|
$this->DrawXLabel();
|
|
$this->DrawYLabel();
|
|
return true;
|
|
}
|
|
|
|
function DrawXLabel() {
|
|
if ($this->use_ttf == 1) {
|
|
$xpos = $this->xtr(($this->plot_max_x + $this->plot_min_x)/2.0) ;
|
|
$ypos = $this->ytr($this->plot_min_y) + $this->x_label_height/2.0;
|
|
$this->DrawText($this->x_label_ttffont, $this->x_label_angle,
|
|
$xpos, $ypos, $this->ndx_label_color, $this->x_label_ttffont_size, $this->x_label_txt,'center');
|
|
} else {
|
|
|
|
$xpos = 0.0 + $this->xtr(($this->plot_max_x+$this->plot_min_x)/2.0) ;
|
|
$ypos = ($this->ytr($this->plot_min_y) + $this->x_label_height/2);
|
|
|
|
$this->DrawText($this->small_font, $this->x_label_angle,
|
|
$xpos, $ypos, $this->ndx_label_color, "", $this->x_label_txt, 'center');
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawYLabel() {
|
|
if ($this->use_ttf == 1) {
|
|
$size = $this->TTFBBoxSize($this->y_label_ttffont_size, 90, $this->y_label_ttffont, $this->y_label_txt);
|
|
$xpos = 8 + $size[0];
|
|
$ypos = ($size[1])/2 + $this->ytr(($this->plot_max_y + $this->plot_min_y)/2.0) ;
|
|
$this->DrawText($this->y_label_ttffont, 90,
|
|
$xpos, $ypos, $this->ndx_label_color, $this->y_label_ttffont_size, $this->y_label_txt);
|
|
} else {
|
|
$xpos = 8;
|
|
$ypos = (($this->small_font_width*strlen($this->y_label_txt)/2.0) +
|
|
$this->ytr(($this->plot_max_y + $this->plot_min_y)/2.0) );
|
|
$this->DrawText($this->small_font, 90,
|
|
$xpos, $ypos, $this->ndx_label_color, $this->y_label_ttffont_size, $this->y_label_txt);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawText($which_font,$which_angle,$which_xpos,$which_ypos,$which_color,$which_size,$which_text,$which_halign='left',$which_valign='') {
|
|
|
|
if ($this->use_ttf == 1 ) {
|
|
$size = $this->TTFBBoxSize($which_size, $which_angle, $which_font, $which_text);
|
|
if ($which_valign == 'bottom') {
|
|
$which_ypos = $which_ypos + ImageFontHeight($which_font);
|
|
}
|
|
if ($which_halign == 'center') {
|
|
$which_xpos = $which_xpos - $size[0]/2;
|
|
}
|
|
ImageTTFText($this->img, $which_size, $which_angle,
|
|
$which_xpos, $which_ypos, $which_color, $which_font, $which_text);
|
|
} else {
|
|
if ($which_valign == 'top') {
|
|
$which_ypos = $which_ypos - ImageFontHeight($which_font);
|
|
}
|
|
$which_text = ereg_replace("\r","",$which_text);
|
|
$str = split("\n",$which_text); //multiple lines submitted by Remi Ricard
|
|
$height = ImageFontHeight($which_font);
|
|
$width = ImageFontWidth($which_font);
|
|
if ($which_angle == 90) { //Vertical Code Submitted by Marlin Viss
|
|
for($i=0;$i<count($str);$i++) {
|
|
ImageStringUp($this->img, $which_font, ($i*$height + $which_xpos), $which_ypos, $str[$i], $which_color);
|
|
}
|
|
} else {
|
|
for($i=0;$i<count($str);$i++) {
|
|
if ($which_halign == 'center') {
|
|
$xpos = $which_xpos - strlen($str[$i]) * $width/2;
|
|
ImageString($this->img, $which_font, $xpos, ($i*$height + $which_ypos), $str[$i], $which_color);
|
|
} else {
|
|
ImageString($this->img, $which_font, $which_xpos, ($i*$height + $which_ypos), $str[$i], $which_color);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return true;
|
|
|
|
}
|
|
function DrawTitle() {
|
|
if ($this->use_ttf == 1 ) {
|
|
$xpos = ($this->plot_area[0] + $this->plot_area_width / 2);
|
|
$ypos = $this->y_top_margin/2;
|
|
$this->DrawText($this->title_ttffont, $this->title_angle,
|
|
$xpos, $ypos, $this->ndx_title_color, $this->title_ttffont_size, $this->title_txt,'center');
|
|
} else {
|
|
$xpos = ($this->plot_area[0] + $this->plot_area_width / 2);
|
|
$ypos = ImageFontHeight($this->title_font);
|
|
$this->DrawText($this->title_font, $this->title_angle,
|
|
$xpos, $ypos, $this->ndx_title_color, '', $this->title_txt,'center');
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
function DrawPlotAreaBackground() {
|
|
ImageFilledRectangle($this->img,$this->plot_area[0],
|
|
$this->plot_area[1],$this->plot_area[2],$this->plot_area[3],
|
|
$this->ndx_plot_bg_color);
|
|
}
|
|
|
|
function SetBackgroundColor($which_color) {
|
|
$this->bg_color= $which_color;
|
|
$this->ndx_bg_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
function SetPlotBgColor($which_color) {
|
|
$this->plot_bg_color= $which_color;
|
|
$this->ndx_plot_bg_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetShading($which_s) {
|
|
$this->shading = $which_s;
|
|
return true;
|
|
}
|
|
|
|
function SetTitleColor($which_color) {
|
|
$this->title_color= $which_color;
|
|
$this->ndx_title_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetTickColor ($which_color) {
|
|
$this->tick_color= $which_color;
|
|
$this->ndx_tick_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetLabelColor ($which_color) {
|
|
$this->label_color= $which_color;
|
|
$this->ndx_label_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetTextColor ($which_color) {
|
|
$this->text_color= $which_color;
|
|
$this->ndx_text_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetLightGridColor ($which_color) {
|
|
$this->light_grid_color= $which_color;
|
|
$this->ndx_light_grid_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetGridColor ($which_color) {
|
|
$this->grid_color = $which_color;
|
|
$this->ndx_grid_color= $this->SetIndexColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetCharacterHeight() {
|
|
//to be set
|
|
return true;
|
|
}
|
|
|
|
function SetPlotType($which_pt) {
|
|
$accepted = "bars,lines,linepoints,area,points,pie,thinbarline";
|
|
$asked = trim($which_pt);
|
|
if (eregi($asked, $accepted)) {
|
|
$this->plot_type = $which_pt;
|
|
return true;
|
|
} else {
|
|
$this->DrawError('$which_pt not an acceptable plot type');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function FindDataLimits() {
|
|
//Text-Data is different than data-data graphs. For them what
|
|
// we have, instead of X values, is # of records equally spaced on data.
|
|
//text-data is passed in as $data[] = (title,y1,y2,y3,y4,...)
|
|
//data-data is passed in as $data[] = (title,x,y1,y2,y3,y4,...)
|
|
|
|
$this->number_x_points = count($this->data_values);
|
|
|
|
switch ($this->data_type) {
|
|
case "text-data":
|
|
$minx = 0; //valid for BAR TYPE GRAPHS ONLY
|
|
$maxx = $this->number_x_points - 1 ; //valid for BAR TYPE GRAPHS ONLY
|
|
$miny = (double) $this->data_values[0][1];
|
|
$maxy = $miny;
|
|
if ($this->draw_x_data_labels == "") {
|
|
$this->draw_x_data_labels = 1; //labels_note1: prevent both data labels and x-axis labels being both drawn and overlapping
|
|
}
|
|
break;
|
|
default: //Everything else: data-data, etc.
|
|
$maxx = $this->data_values[0][1];
|
|
$minx = $maxx;
|
|
$miny = $this->data_values[0][2];
|
|
$maxy = $miny;
|
|
$maxy = $miny;
|
|
break;
|
|
}
|
|
|
|
$max_records_per_group = 0;
|
|
$total_records = 0;
|
|
$mine = 0; //Maximum value for the -error bar (assume error bars always > 0)
|
|
$maxe = 0; //Maximum value for the +error bar (assume error bars always > 0)
|
|
|
|
reset($this->data_values);
|
|
while (list($dat_key, $dat) = each($this->data_values)) { //for each X barchart setting
|
|
//foreach($this->data_values as $dat) //can use foreach only in php4
|
|
|
|
$tmp = 0;
|
|
$total_records += count($dat) - 1; // -1 for label
|
|
|
|
switch ($this->data_type) {
|
|
case "text-data":
|
|
//Find the relative Max and Min
|
|
|
|
while (list($key, $val) = each($dat)) {
|
|
if ($key != 0) { //$dat[0] = label
|
|
SetType($val,"double");
|
|
if ($val > $maxy) {
|
|
$maxy = $val ;
|
|
}
|
|
if ($val < $miny) {
|
|
$miny = (double) $val ;
|
|
}
|
|
}
|
|
$tmp++;
|
|
}
|
|
break;
|
|
case "data-data": //X-Y data is passed in as $data[] = (title,x,y,y2,y3,...) which you can use for multi-dimentional plots.
|
|
|
|
while (list($key, $val) = each($dat)) {
|
|
if ($key == 1) { //$dat[0] = label
|
|
SetType($val,"double");
|
|
if ($val > $maxx) {
|
|
$maxx = $val;
|
|
} elseif ($val < $minx) {
|
|
$minx = $val;
|
|
}
|
|
} elseif ($key > 1) {
|
|
SetType($val,"double");
|
|
if ($val > $maxy) {
|
|
$maxy = $val ;
|
|
} elseif ($val < $miny) {
|
|
$miny = $val ;
|
|
}
|
|
}
|
|
$tmp++;
|
|
}
|
|
$tmp = $tmp - 1; //# records per group
|
|
break;
|
|
case "data-data-error": //Assume 2-D for now, can go higher
|
|
//Regular X-Y data is passed in as $data[] = (title,x,y,error+,error-,y2,error2+,error2-)
|
|
|
|
while (list($key, $val) = each($dat)) {
|
|
if ($key == 1) { //$dat[0] = label
|
|
SetType($val,'double');
|
|
if ($val > $maxx) {
|
|
$maxx = $val;
|
|
} elseif ($val < $minx) {
|
|
$minx = $val;
|
|
}
|
|
} elseif ($key%3 == 2) {
|
|
SetType($val,'double');
|
|
if ($val > $maxy) {
|
|
$maxy = $val ;
|
|
} elseif ($val < $miny) {
|
|
$miny = $val ;
|
|
}
|
|
} elseif ($key%3 == 0) {
|
|
SetType($val,'double');
|
|
if ($val > $maxe) {
|
|
$maxe = $val ;
|
|
}
|
|
} elseif ($key%3 == 1) {
|
|
SetType($val,'double');
|
|
if ($val > $mine) {
|
|
$mine = $val ;
|
|
}
|
|
}
|
|
$tmp++;
|
|
}
|
|
$maxy = $maxy + $maxe;
|
|
$miny = $miny - $mine; //assume error bars are always > 0
|
|
|
|
break;
|
|
default:
|
|
$this->PrintError('ERROR: unknown chart type');
|
|
break;
|
|
}
|
|
if ($tmp > $max_records_per_group) {
|
|
$max_records_per_group = $tmp;
|
|
}
|
|
}
|
|
|
|
|
|
$this->min_x = $minx;
|
|
$this->max_x = $maxx;
|
|
$this->min_y = $miny;
|
|
$this->max_y = $maxy;
|
|
|
|
|
|
if ($max_records_per_group > 1) {
|
|
$this->records_per_group = $max_records_per_group - 1;
|
|
} else {
|
|
$this->records_per_group = 1;
|
|
}
|
|
|
|
|
|
//$this->data_count = $total_records ;
|
|
} // function FindDataLimits
|
|
|
|
function SetMargins() {
|
|
/////////////////////////////////////////////////////////////////
|
|
// When the image is first created - set the margins
|
|
// to be the standard viewport.
|
|
// The standard viewport is the full area of the view surface (or panel),
|
|
// less a margin of 4 character heights all round for labelling.
|
|
// It thus depends on the current character size, set by SetCharacterHeight().
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
$str = split("\n",$this->title_txt);
|
|
$nbLines = count($str);
|
|
|
|
if ($this->use_ttf == 1) {
|
|
$title_size = $this->TTFBBoxSize($this->title_ttffont_size, $this->title_angle, $this->title_ttffont, 'X'); //An array
|
|
if ($nbLines == 1) {
|
|
$this->y_top_margin = $title_size[1] * 4;
|
|
} else {
|
|
$this->y_top_margin = $title_size[1] * ($nbLines+3);
|
|
}
|
|
|
|
//ajo working here
|
|
//$x_label_size = $this->TTFBBoxSize($this->x_label_ttffont_size, 0, $this->axis_ttffont, $this->x_label_txt);
|
|
|
|
$this->y_bot_margin = $this->x_label_height ;
|
|
$this->x_left_margin = $this->y_label_width * 2 + $this->tick_length;
|
|
$this->x_right_margin = 33.0; // distance between right and end of x axis in pixels
|
|
} else {
|
|
$title_size = array(ImageFontWidth($this->title_font) * strlen($this->title_txt),ImageFontHeight($this->title_font));
|
|
//$this->y_top_margin = ($title_size[1] * 4);
|
|
if ($nbLines == 1) {
|
|
$this->y_top_margin = $title_size[1] * 4;
|
|
} else {
|
|
$this->y_top_margin = $title_size[1] * ($nbLines+3);
|
|
}
|
|
if ($this->x_datalabel_angle == 90) {
|
|
$this->y_bot_margin = 76.0; // Must be integer
|
|
} else {
|
|
$this->y_bot_margin = 66.0; // Must be integer
|
|
}
|
|
$this->x_left_margin = 77.0; // distance between left and start of x axis in pixels
|
|
$this->x_right_margin = 33.0; // distance between right and end of x axis in pixels
|
|
}
|
|
|
|
//exit;
|
|
$this->x_tot_margin = $this->x_left_margin + $this->x_right_margin;
|
|
$this->y_tot_margin = $this->y_top_margin + $this->y_bot_margin;
|
|
|
|
if ($this->plot_max_x && $this->plot_max_y && $this->plot_area_width ) { //If data has already been analysed then set translation
|
|
$this->SetTranslation();
|
|
}
|
|
}
|
|
|
|
function SetMarginsPixels($which_lm,$which_rm,$which_tm,$which_bm) {
|
|
//Set the plot area using margins in pixels (left, right, top, bottom)
|
|
$this->SetNewPlotAreaPixels($which_lm,$which_tm,($this->image_width - $which_rm),($this->image_height - $which_bm));
|
|
return true;
|
|
}
|
|
|
|
function SetNewPlotAreaPixels($x1,$y1,$x2,$y2) {
|
|
//Like in GD 0,0 is upper left set via pixel Coordinates
|
|
$this->plot_area = array($x1,$y1,$x2,$y2);
|
|
$this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
|
|
$this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
|
|
$this->y_top_margin = $this->plot_area[1];
|
|
if ($this->plot_max_x) {
|
|
$this->SetTranslation();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetPlotAreaPixels($x1,$y1,$x2,$y2) {
|
|
//Like in GD 0,0 is upper left
|
|
if (!$this->x_tot_margin) {
|
|
$this->SetMargins();
|
|
}
|
|
if ($x2 && $y2) {
|
|
$this->plot_area = array($x1,$y1,$x2,$y2);
|
|
} else {
|
|
$this->plot_area = array($this->x_left_margin, $this->y_top_margin,
|
|
$this->image_width - $this->x_right_margin,
|
|
$this->image_height - $this->y_bot_margin
|
|
);
|
|
}
|
|
$this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
|
|
$this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
function SetPlotAreaWorld($xmin,$ymin,$xmax,$ymax)
|
|
{
|
|
if (($xmin == "") && ($xmax == ""))
|
|
{
|
|
//For automatic setting of data we need $this->max_x
|
|
if (!$this->max_y)
|
|
{
|
|
$this->FindDataLimits() ;
|
|
}
|
|
if ($this->data_type == 'text-data') { //labels for text-data is done at data drawing time for speed.
|
|
$xmax = $this->max_x + 1 ; //valid for BAR CHART TYPE GRAPHS ONLY
|
|
$xmin = 0 ; //valid for BAR CHART TYPE GRAPHS ONLY
|
|
} else {
|
|
$xmax = $this->max_x * 1.02;
|
|
$xmin = $this->min_x;
|
|
}
|
|
|
|
$ymax = ceil($this->max_y * 1.2);
|
|
if ($this->min_y < 0) {
|
|
$ymin = floor($this->min_y * 1.2);
|
|
} else {
|
|
$ymin = 0;
|
|
}
|
|
}
|
|
|
|
$this->plot_min_x = $xmin;
|
|
$this->plot_max_x = $xmax;
|
|
|
|
if ($ymin == $ymax) {
|
|
$ymax += 1;
|
|
}
|
|
if ($this->yscale_type == "log") {
|
|
//extra error checking
|
|
if ($ymin <= 0) {
|
|
$ymin = 1;
|
|
}
|
|
if ($ymax <= 0) {
|
|
$this->PrintError('Log plots need data greater than 0');
|
|
}
|
|
}
|
|
$this->plot_min_y = $ymin;
|
|
$this->plot_max_y = $ymax;
|
|
|
|
if ($ymax <= $ymin) {
|
|
$this->DrawError('Error in Data - max not gt min');
|
|
}
|
|
|
|
//Set the boundaries of the box for plotting in world coord
|
|
// if (!$this->x_tot_margin) { //We need to know the margins before we can calculate scale
|
|
// $this->SetMargins();
|
|
// }
|
|
//For this we have to reset the scale
|
|
if ($this->plot_area_width) {
|
|
$this->SetTranslation();
|
|
}
|
|
|
|
return true;
|
|
|
|
} //function SetPlotAreaWorld
|
|
|
|
|
|
function PrintError($error_message) {
|
|
// prints the error message to stdout and die
|
|
echo "<p><b>Fatal error</b>: $error_message<p>";
|
|
die;
|
|
}
|
|
|
|
function DrawError($error_message) {
|
|
// prints the error message inline into
|
|
// the generated image
|
|
|
|
if (($this->img) == "") { $this->InitImage(); } ;
|
|
|
|
$ypos = $this->image_height/2;
|
|
|
|
if ($this->use_ttf == 1) {
|
|
ImageRectangle($this->img, 0,0,$this->image_width,$this->image_height,ImageColorAllocate($this->img,255,255,255));
|
|
ImageTTFText($this->img, $this->small_ttffont_size, 0, $xpos, $ypos, ImageColorAllocate($this->img,0,0,0), $this->axis_ttffont, $error_message);
|
|
} else {
|
|
ImageRectangle($this->img, 0,0,$this->image_width,$this->image_height,ImageColorAllocate($this->img,255,255,255));
|
|
ImageString($this->img, $this->small_font,1,$ypos,$error_message, ImageColorAllocate($this->img,0,0,0));
|
|
}
|
|
|
|
$this->PrintImage();
|
|
return true;
|
|
}
|
|
|
|
function TTFBBoxSize($size, $angle, $font, $string) {
|
|
|
|
//Assume angle < 90
|
|
$arr = ImageTTFBBox($size, 0, $font, $string);
|
|
$flat_width = $arr[0] - $arr[2];
|
|
$flat_height = abs($arr[3] - $arr[5]);
|
|
|
|
// for 90deg:
|
|
// $height = $arr[5] - $arr[7];
|
|
// $width = $arr[2] - $arr[4];
|
|
|
|
$angle = deg2rad($angle);
|
|
$width = ceil(abs($flat_width*cos($angle) + $flat_height*sin($angle))); //Must be integer
|
|
$height = ceil(abs($flat_width*sin($angle) + $flat_height*cos($angle))); //Must be integer
|
|
|
|
return array($width, $height);
|
|
}
|
|
|
|
function SetXLabelHeight() {
|
|
|
|
if ($this->use_ttf == 1) {
|
|
//Space for the X Label
|
|
$size = $this->TTFBBoxSize($this->x_label_ttffont_size, 0, $this->axis_ttffont, $this->x_label_txt);
|
|
$tmp = $size[1];
|
|
|
|
//$string = Str_Repeat('w', $this->x_datalabel_maxlength);
|
|
$i = 0;
|
|
$string = '';
|
|
while ($i < $this->x_datalabel_maxlength) {
|
|
$string .= 'w';
|
|
$i++;
|
|
}
|
|
|
|
//Space for the axis data labels
|
|
$size = $this->TTFBBoxSize($this->axis_ttffont_size, $this->x_datalabel_angle, $this->axis_ttffont, $string);
|
|
|
|
$this->x_label_height = 2*$tmp + $size[1] + 4;
|
|
|
|
} else {
|
|
//For Non-TTF fonts we can have only angles 0 or 90
|
|
if ($this->x_datalabel_angle == 90) {
|
|
$this->x_label_height = $this->x_datalabel_maxlength * ImageFontWidth($this->small_font) / 1.5;
|
|
} else {
|
|
$this->x_label_height = 5 * ImageFontHeight($this->small_font);
|
|
}
|
|
}
|
|
|
|
$this->SetMargins();
|
|
|
|
return true;
|
|
} //function SetXLabelHeight
|
|
|
|
function SetYLabelWidth() {
|
|
//$ylab = sprintf("%6.1f %s",$i,$si_units[0]); //use for PHP2 compatibility
|
|
//the "." is for space. It isn't actually printed
|
|
$ylab = number_format($this->max_y, $this->y_precision, ".", ",") . $this->si_units . ".";
|
|
|
|
if ($this->use_ttf == 1) {
|
|
$size = $this->TTFBBoxSize($this->axis_ttffont_size, 0, $this->axis_ttffont, $ylab);
|
|
} else {
|
|
$size[0] = StrLen($ylab) * $this->small_font_width * .6;
|
|
}
|
|
|
|
$this->y_label_width = $size[0] * 2;
|
|
//echo "SYLW: $this->y_label_width<br>";
|
|
//exit;
|
|
|
|
$this->SetMargins();
|
|
return true;
|
|
}
|
|
|
|
function SetEqualXCoord() {
|
|
//for plots that have equally spaced x variables and multiple bars per x-point.
|
|
|
|
$space = ($this->plot_area[2] - $this->plot_area[0]) / ($this->number_x_points * 2) * $this->group_frac_width;
|
|
$group_width = $space * 2;
|
|
$bar_width = $group_width / $this->records_per_group;
|
|
//I think that eventually this space variable will be replaced by just graphing x.
|
|
$this->data_group_space = $space;
|
|
$this->record_bar_width = $bar_width;
|
|
return true;
|
|
}
|
|
|
|
function SetLabelScalePosition($which_blp) {
|
|
//0 to 1
|
|
$this->label_scale_position = $which_blp;
|
|
return true;
|
|
}
|
|
|
|
function SetErrorBarSize($which_ebs) {
|
|
//in pixels
|
|
$this->error_bar_size = $which_ebs;
|
|
return true;
|
|
}
|
|
|
|
function SetErrorBarShape($which_ebs) {
|
|
//in pixels
|
|
$this->error_bar_shape = $which_ebs;
|
|
return true;
|
|
}
|
|
|
|
function SetPointShape($which_pt) {
|
|
//in pixels
|
|
$this->point_shape = $which_pt;
|
|
return true;
|
|
}
|
|
|
|
function SetPointSize($which_ps) {
|
|
//in pixels
|
|
SetType($which_ps,'integer');
|
|
$this->point_size = $which_ps;
|
|
|
|
if ($this->point_shape == "diamond" or $this->point_shape == "triangle") {
|
|
if ($this->point_size % 2 != 0) {
|
|
$this->point_size++;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetDataType($which_dt) {
|
|
//The next three lines are for past compatibility.
|
|
if ($which_dt == "text-linear") { $which_dt = "text-data"; };
|
|
if ($which_dt == "linear-linear") { $which_dt = "data-data"; };
|
|
if ($which_dt == "linear-linear-error") { $which_dt = "data-data-error"; };
|
|
|
|
$this->data_type = $which_dt; //text-data, data-data, data-data-error
|
|
return true;
|
|
}
|
|
|
|
function SetDataValues($which_dv) {
|
|
$this->data_values = $which_dv;
|
|
//echo $this->data_values
|
|
return true;
|
|
}
|
|
|
|
//////////////COLORS
|
|
function SetRGBArray ($which_color_array) {
|
|
if ( is_array($which_color_array) ) {
|
|
//User Defined Array
|
|
$this->rgb_array = $which_color_array;
|
|
return true;
|
|
} elseif ($which_color_array == 2) { //Use the small predefined color array
|
|
$this->rgb_array = array(
|
|
"white" => array(255, 255, 255),
|
|
"snow" => array(255, 250, 250),
|
|
"PeachPuff" => array(255, 218, 185),
|
|
"ivory" => array(255, 255, 240),
|
|
"lavender" => array(230, 230, 250),
|
|
"black" => array( 0, 0, 0),
|
|
"DimGrey" => array(105, 105, 105),
|
|
"gray" => array(190, 190, 190),
|
|
"grey" => array(190, 190, 190),
|
|
"navy" => array( 0, 0, 128),
|
|
"SlateBlue" => array(106, 90, 205),
|
|
"blue" => array( 0, 0, 255),
|
|
"SkyBlue" => array(135, 206, 235),
|
|
"cyan" => array( 0, 255, 255),
|
|
"DarkGreen" => array( 0, 100, 0),
|
|
"green" => array( 0, 255, 0),
|
|
"YellowGreen" => array(154, 205, 50),
|
|
"yellow" => array(255, 255, 0),
|
|
"orange" => array(255, 165, 0),
|
|
"gold" => array(255, 215, 0),
|
|
"peru" => array(205, 133, 63),
|
|
"beige" => array(245, 245, 220),
|
|
"wheat" => array(245, 222, 179),
|
|
"tan" => array(210, 180, 140),
|
|
"brown" => array(165, 42, 42),
|
|
"salmon" => array(250, 128, 114),
|
|
"red" => array(255, 0, 0),
|
|
"pink" => array(255, 192, 203),
|
|
"maroon" => array(176, 48, 96),
|
|
"magenta" => array(255, 0, 255),
|
|
"violet" => array(238, 130, 238),
|
|
"plum" => array(221, 160, 221),
|
|
"orchid" => array(218, 112, 214),
|
|
"purple" => array(160, 32, 240),
|
|
"azure1" => array(240, 255, 255),
|
|
"aquamarine1" => array(127, 255, 212)
|
|
);
|
|
return true;
|
|
} elseif ($which_color_array == 1) {
|
|
include("./rgb.inc.php"); //Get large $ColorArray
|
|
$this->rgb_array = $RGBArray;
|
|
} else {
|
|
$this->rgb_array = array("white" =>array(255,255,255), "black" => array(0,0,0));
|
|
exit;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function SetColor($which_color) {
|
|
//obsoleted by SetRGBColor
|
|
SetRgbColor($which_color);
|
|
return true;
|
|
}
|
|
|
|
function SetIndexColor($which_color) { //Color is passed in as anything
|
|
list ($r, $g, $b) = $this->SetRgbColor($which_color); //Translate to RGB
|
|
$index = ImageColorExact($this->img, $r, $g, $b);
|
|
if ($index == -1) {
|
|
//return ImageColorAllocate($this->img, $r, $g, $b);
|
|
//return ImageColorClosest($this->img, $r, $g, $b);
|
|
return ImageColorResolve($this->img, $r, $g, $b); //requires PHP 3.0.2 and later
|
|
} else {
|
|
return $index;
|
|
}
|
|
}
|
|
|
|
function SetTransparentColor($which_color) {
|
|
ImageColorTransparent($this->img,$this->SetIndexColor($which_color));
|
|
return true;
|
|
}
|
|
|
|
function SetRgbColor($color_asked) {
|
|
//Returns an array in R,G,B format 0-255
|
|
if ($color_asked == "") { $color_asked = array(0,0,0); };
|
|
|
|
if ( count($color_asked) == 3 ) { //already array of 3 rgb
|
|
$ret_val = $color_asked;
|
|
} else { // is asking for a color by string
|
|
if(substr($color_asked,0,1) == "#") { //asking in #FFFFFF format.
|
|
$ret_val = array(hexdec(substr($color_asked,1,2)), hexdec(substr($color_asked,3,2)), hexdec(substr($color,5,2)));
|
|
} else {
|
|
$ret_val = $this->rgb_array[$color_asked];
|
|
}
|
|
}
|
|
return $ret_val;
|
|
}
|
|
|
|
function SetDataColors($which_data,$which_border) {
|
|
//Set the data to be displayed in a particular color
|
|
if (!$which_data) {
|
|
$which_data = array(array(0,255,0),array(0,0,248),'yellow',array(255,0,0),'orange');
|
|
$which_border = array('black');
|
|
}
|
|
|
|
$this->data_color = $which_data; //an array
|
|
$this->data_border_color = $which_border; //an array
|
|
|
|
unset($this->ndx_data_color);
|
|
reset($this->data_color); //data_color can be an array of colors, one for each thing plotted
|
|
//while (list(, $col) = each($this->data_color))
|
|
$i = 0;
|
|
while (list(, $col) = each($which_data)) {
|
|
$this->ndx_data_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
|
|
// border_color
|
|
//If we are also going to put a border on the data (bars, dots, area, ...)
|
|
// then lets also set a border color as well.
|
|
//foreach($this->data_border_color as $col)
|
|
unset($this->ndx_data_border_color);
|
|
reset($this->data_border_color);
|
|
$i = 0;
|
|
while (list(, $col) = each($this->data_border_color)) {
|
|
$this->ndx_data_border_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
|
|
//Set color of the error bars to be that of data if not already set.
|
|
if (!$this->error_bar_color) {
|
|
reset($which_data);
|
|
$this->SetErrorBarColors($which_data);
|
|
}
|
|
|
|
return true;
|
|
|
|
} //function SetDataColors
|
|
|
|
function SetErrorBarColors($which_data) {
|
|
|
|
//Set the data to be displayed in a particular color
|
|
|
|
if ($which_data) {
|
|
$this->error_bar_color = $which_data; //an array
|
|
unset($this->ndx_error_bar_color);
|
|
reset($this->error_bar_color); //data_color can be an array of colors, one for each thing plotted
|
|
$i = 0;
|
|
while (list(, $col) = each($this->error_bar_color)) {
|
|
$this->ndx_error_bar_color[$i] = $this->SetIndexColor($col);
|
|
$i++;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
} //function SetErrorBarColors
|
|
|
|
|
|
function DrawPlotBorder() {
|
|
switch ($this->plot_border_type) {
|
|
case "left" :
|
|
ImageLine($this->img, $this->plot_area[0],$this->ytr($this->plot_min_y),
|
|
$this->plot_area[0],$this->ytr($this->plot_max_y),$this->ndx_grid_color);
|
|
break;
|
|
case "none":
|
|
//Draw No Border
|
|
break;
|
|
default:
|
|
ImageRectangle($this->img, $this->plot_area[0],$this->ytr($this->plot_min_y),
|
|
$this->plot_area[2],$this->ytr($this->plot_max_y),$this->ndx_grid_color);
|
|
break;
|
|
}
|
|
$this->DrawYAxis();
|
|
$this->DrawXAxis();
|
|
return true;
|
|
}
|
|
|
|
|
|
function SetHorizTickIncrement($which_ti) {
|
|
//Use either this or NumHorizTicks to set where to place x tick marks
|
|
if ($which_ti) {
|
|
$this->horiz_tick_increment = $which_ti; //world coordinates
|
|
} else {
|
|
if (!$this->max_x) {
|
|
$this->FindDataLimits(); //Get maxima and minima for scaling
|
|
}
|
|
//$this->horiz_tick_increment = ( ceil($this->max_x * 1.2) - floor($this->min_x * 1.2) )/10;
|
|
$this->horiz_tick_increment = ($this->plot_max_x - $this->plot_min_x )/10;
|
|
}
|
|
$this->num_horiz_ticks = ''; //either use num_vert_ticks or vert_tick_increment, not both
|
|
return true;
|
|
}
|
|
|
|
function SetDrawVertTicks($which_dvt) {
|
|
$this->draw_vert_ticks = $which_dvt;
|
|
return true;
|
|
}
|
|
|
|
function SetVertTickIncrement($which_ti) {
|
|
//Use either this or NumVertTicks to set where to place y tick marks
|
|
if ($which_ti) {
|
|
$this->vert_tick_increment = $which_ti; //world coordinates
|
|
} else {
|
|
if (!$this->max_y) {
|
|
$this->FindDataLimits(); //Get maxima and minima for scaling
|
|
}
|
|
//$this->vert_tick_increment = ( ceil($this->max_y * 1.2) - floor($this->min_y * 1.2) )/10;
|
|
$this->vert_tick_increment = ($this->plot_max_y - $this->plot_min_y )/10;
|
|
}
|
|
$this->num_vert_ticks = ''; //either use num_vert_ticks or vert_tick_increment, not both
|
|
return true;
|
|
}
|
|
|
|
function SetNumHorizTicks($which_nt) {
|
|
$this->num_horiz_ticks = $which_nt;
|
|
$this->horiz_tick_increment = ''; //either use num_horiz_ticks or horiz_tick_increment, not both
|
|
return true;
|
|
}
|
|
|
|
function SetNumVertTicks($which_nt) {
|
|
$this->num_vert_ticks = $which_nt;
|
|
$this->vert_tick_increment = ''; //either use num_vert_ticks or vert_tick_increment, not both
|
|
return true;
|
|
}
|
|
function SetVertTickPosition($which_tp) {
|
|
$this->vert_tick_position = $which_tp; //plotleft, plotright, both, yaxis
|
|
return true;
|
|
}
|
|
function SetSkipBottomTick($which_sbt) {
|
|
$this->skip_bottom_tick = $which_sbt;
|
|
return true;
|
|
}
|
|
|
|
function SetTickLength($which_tl) {
|
|
$this->tick_length = $which_tl;
|
|
return true;
|
|
}
|
|
|
|
function DrawYAxis() {
|
|
//Draw Line at left side or at this->y_axis_position
|
|
if ($this->y_axis_position != "") {
|
|
$yaxis_x = $this->xtr($this->y_axis_position);
|
|
} else {
|
|
$yaxis_x = $this->plot_area[0];
|
|
}
|
|
|
|
ImageLine($this->img, $yaxis_x, $this->plot_area[1],
|
|
$yaxis_x, $this->plot_area[3], $this->ndx_grid_color);
|
|
//$yaxis_x, $this->plot_area[3], 9);
|
|
|
|
if ($this->draw_vert_ticks == 1) {
|
|
$this->DrawVerticalTicks();
|
|
}
|
|
|
|
} //function DrawYAxis
|
|
|
|
function DrawXAxis() {
|
|
//Draw Tick and Label for Y axis
|
|
$ylab =$this->FormatYTickLabel($this->x_axis_position);
|
|
if ($this->skip_bottom_tick != 1) {
|
|
$this->DrawVerticalTick($ylab,$this->x_axis_position);
|
|
}
|
|
|
|
//Draw X Axis at Y=$x_axis_postion
|
|
ImageLine($this->img,$this->plot_area[0]+1,$this->ytr($this->x_axis_position),
|
|
$this->xtr($this->plot_max_x)-1,$this->ytr($this->x_axis_position),$this->ndx_tick_color);
|
|
|
|
//X Ticks and Labels
|
|
if ($this->data_type != 'text-data') { //labels for text-data done at data drawing time for speed.
|
|
$this->DrawHorizontalTicks();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawHorizontalTicks() {
|
|
//Ticks and lables are drawn on the left border of PlotArea.
|
|
//Left Bottom
|
|
ImageLine($this->img,$this->plot_area[0],
|
|
$this->plot_area[3]+$this->tick_length,
|
|
$this->plot_area[0],$this->plot_area[3],$this->ndx_tick_color);
|
|
|
|
switch ($this->x_grid_label_type) {
|
|
case "title":
|
|
$xlab = $this->data_values[0][0];
|
|
break;
|
|
case "data":
|
|
$xlab = number_format($this->plot_min_x,$this->x_precision,".",",") . "$this->si_units";
|
|
break;
|
|
case "none":
|
|
$xlab = '';
|
|
break;
|
|
case "time": //Time formatting suggested by Marlin Viss
|
|
$xlab = strftime($this->x_time_format,$this->plot_min_x);
|
|
break;
|
|
default:
|
|
//Unchanged from whatever format is passed in
|
|
$xlab = $this->plot_min_x;
|
|
break;
|
|
}
|
|
|
|
if ($this->x_datalabel_angle == 90) {
|
|
$xpos = $this->plot_area[0] - $this->small_font_height/2;
|
|
$ypos = ( $this->small_font_width*strlen($xlab) + $this->plot_area[3] + $this->small_font_height);
|
|
ImageStringUp($this->img, $this->small_font,$xpos, $ypos, $xlab, $this->ndx_text_color);
|
|
} else {
|
|
$xpos = $this->plot_area[0] - $this->small_font_width*strlen($xlab)/2 ;
|
|
$ypos = $this->plot_area[3] + $this->small_font_height;
|
|
ImageString($this->img, $this->small_font,$xpos, $ypos, $xlab, $this->ndx_text_color);
|
|
}
|
|
|
|
//Will be changed to allow for TTF fonts in data as well.
|
|
//$this->DrawText($this->small_font, $this->x_datalabel_angle, $xpos, $ypos, $this->ndx_title_color, '', $xlab);
|
|
|
|
//Top
|
|
|
|
if ($this->horiz_tick_increment) {
|
|
$delta_x = $this->horiz_tick_increment;
|
|
} elseif ($this->num_horiz_ticks) {
|
|
$delta_x = ($this->plot_max_x - $this->plot_min_x) / $this->num_horiz_ticks;
|
|
} else {
|
|
$delta_x =($this->plot_max_x - $this->plot_min_x) / 10 ;
|
|
}
|
|
|
|
$i = 0;
|
|
$x_tmp = $this->plot_min_x;
|
|
SetType($x_tmp,'double');
|
|
|
|
while ($x_tmp <= $this->plot_max_x){
|
|
//$xlab = sprintf("%6.1f %s",$min_x,$si_units[0]); //PHP2 past compatibility
|
|
switch ($this->x_grid_label_type) {
|
|
case "title":
|
|
$xlab = $this->data_values[$x_tmp][0];
|
|
break;
|
|
case "data":
|
|
$xlab = number_format($x_tmp,$this->x_precision,".",",") . "$this->si_units";
|
|
break;
|
|
case "none":
|
|
$xlab = '';
|
|
break;
|
|
case "time": //Time formatting suggested by Marlin Viss
|
|
$xlab = strftime($this->x_time_format,$x_tmp);
|
|
break;
|
|
default:
|
|
//Unchanged from whatever format is passed in
|
|
$xlab = $x_tmp;
|
|
break;
|
|
}
|
|
|
|
$x_pixels = $this->xtr($x_tmp);
|
|
|
|
//Bottom Tick
|
|
ImageLine($this->img,$x_pixels,$this->plot_area[3] + $this->tick_length,
|
|
$x_pixels,$this->plot_area[3], $this->ndx_tick_color);
|
|
//Top Tick
|
|
//ImageLine($this->img,($this->xtr($this->plot_max_x)+$this->tick_length),
|
|
// $y_pixels,$this->xtr($this->plot_max_x)-1,$y_pixels,$this->ndx_tick_color);
|
|
|
|
if ($this->draw_x_grid == 1) {
|
|
ImageLine($this->img,$x_pixels,$this->plot_area[1],
|
|
$x_pixels,$this->plot_area[3], $this->ndx_light_grid_color);
|
|
}
|
|
|
|
if ($this->x_datalabel_angle == 90) { //Vertical Code Submitted by Marlin Viss
|
|
ImageStringUp($this->img, $this->small_font,
|
|
( $x_pixels - $this->small_font_height/2),
|
|
( $this->small_font_width*strlen($xlab) + $this->plot_area[3] + $this->small_font_height),$xlab, $this->ndx_text_color);
|
|
} else {
|
|
ImageString($this->img, $this->small_font,
|
|
( $x_pixels - $this->small_font_width*strlen($xlab)/2) ,
|
|
( $this->small_font_height + $this->plot_area[3]),$xlab, $this->ndx_text_color);
|
|
}
|
|
|
|
$i++;
|
|
$x_tmp += $delta_x;
|
|
}
|
|
|
|
} // function DrawHorizontalTicks
|
|
|
|
function FormatYTickLabel($which_ylab) {
|
|
switch ($this->y_grid_label_type) {
|
|
case "data":
|
|
$ylab = number_format($which_ylab,$this->y_precision,".",",") . "$this->si_units";
|
|
break;
|
|
case "none":
|
|
$ylab = '';
|
|
break;
|
|
case "time":
|
|
$ylab = strftime($this->y_time_format,$which_ylab);
|
|
break;
|
|
case "right":
|
|
//Make it right aligned
|
|
//$ylab = str_pad($which_ylab,$this->y_label_width," ",STR_PAD_LEFT); //PHP4 only
|
|
$sstr = "%".strlen($this->plot_max_y)."s";
|
|
$ylab = sprintf($sstr,$which_ylab);
|
|
break;
|
|
default:
|
|
//Unchanged from whatever format is passed in
|
|
$ylab = $which_ylab;
|
|
break;
|
|
}
|
|
|
|
return($ylab);
|
|
|
|
} //function FormatYTickLabel
|
|
|
|
function DrawVerticalTick($which_ylab,$which_ypos) { //ylab in world coord.
|
|
//Draw Just one Tick, called from DrawVerticalTicks
|
|
//Ticks and datalables can be left of plot only, right of plot only,
|
|
// both on the left and right of plot, or crossing a user defined Y-axis
|
|
//
|
|
//Its faster to draw both left and right ticks at same time
|
|
// than first left and then right.
|
|
|
|
if ($this->y_axis_position != "") {
|
|
//Ticks and lables are drawn on the left border of yaxis
|
|
$yaxis_x = $this->xtr($this->y_axis_position);
|
|
} else {
|
|
//Ticks and lables are drawn on the left border of PlotArea.
|
|
$yaxis_x = $this->plot_area[0];
|
|
}
|
|
|
|
$y_pixels = $this->ytr($which_ypos);
|
|
|
|
//Lines Across the Plot Area
|
|
if ($this->draw_y_grid == 1) {
|
|
ImageLine($this->img,$this->plot_area[0]+1,$y_pixels,
|
|
$this->plot_area[2]-1,$y_pixels,$this->ndx_light_grid_color);
|
|
}
|
|
|
|
//Ticks to the Left of the Plot Area
|
|
if (($this->vert_tick_position == "plotleft") || ($this->vert_tick_position == "both") ) {
|
|
ImageLine($this->img,(-$this->tick_length+$yaxis_x),
|
|
$y_pixels,$yaxis_x,
|
|
$y_pixels, $this->ndx_tick_color);
|
|
}
|
|
|
|
//Ticks to the Right of the Plot Area
|
|
if (($this->vert_tick_position == "plotright") || ($this->vert_tick_position == "both") ) {
|
|
ImageLine($this->img,($this->plot_area[2]+$this->tick_length),
|
|
$y_pixels,$this->plot_area[2],
|
|
$y_pixels,$this->ndx_tick_color);
|
|
}
|
|
|
|
//Ticks on the Y Axis
|
|
if (($this->vert_tick_position == "yaxis") ) {
|
|
ImageLine($this->img,($yaxis_x - $this->tick_length),
|
|
$y_pixels,$yaxis_x,$y_pixels,$this->ndx_tick_color);
|
|
}
|
|
|
|
//DataLabel
|
|
//ajo working
|
|
//$this->DrawText($this->y_label_ttffont, 0,($yaxis_x - $this->y_label_width - $this->tick_length/2),
|
|
// $y_pixels, $this->ndx_text_color, $this->axis_ttffont_size, $which_ylab);
|
|
ImageString($this->img, $this->small_font, ($yaxis_x - $this->y_label_width - $this->tick_length/2),
|
|
( -($this->small_font_height/2.0) + $y_pixels),$which_ylab, $this->ndx_text_color);
|
|
}
|
|
|
|
function DrawVerticalTicks() {
|
|
|
|
if ($this->skip_top_tick != 1) { //If tick increment doesn't hit the top
|
|
//Left Top
|
|
//ImageLine($this->img,(-$this->tick_length+$this->xtr($this->plot_min_x)),
|
|
// $this->ytr($this->plot_max_y),$this->xtr($this->plot_min_x),$this->ytr($this->plot_max_y),$this->ndx_tick_color);
|
|
//$ylab = $this->FormatYTickLabel($plot_max_y);
|
|
|
|
//Right Top
|
|
//ImageLine($this->img,($this->xtr($this->plot_max_x)+$this->tick_length),
|
|
// $this->ytr($this->plot_max_y),$this->xtr($this->plot_max_x-1),$this->ytr($this->plot_max_y),$this->ndx_tick_color);
|
|
|
|
//Draw Grid Line at Top
|
|
ImageLine($this->img,$this->plot_area[0]+1,$this->ytr($this->plot_max_y),
|
|
$this->plot_area[2]-1,$this->ytr($this->plot_max_y),$this->ndx_light_grid_color);
|
|
|
|
}
|
|
|
|
if ($this->skip_bottom_tick != 1) {
|
|
//Right Bottom
|
|
//ImageLine($this->img,($this->xtr($this->plot_max_x)+$this->tick_length),
|
|
// $this->ytr($this->plot_min_y),$this->xtr($this->plot_max_x),
|
|
// $this->ytr($this->plot_min_y),$this->ndx_tick_color);
|
|
|
|
//Draw Grid Line at Bottom of Plot
|
|
ImageLine($this->img,$this->xtr($this->plot_min_x)+1,$this->ytr($this->plot_min_y),
|
|
$this->xtr($this->plot_max_x),$this->ytr($this->plot_min_y),$this->ndx_light_grid_color);
|
|
}
|
|
|
|
// maxy is always > miny so delta_y is always positive
|
|
if ($this->vert_tick_increment) {
|
|
$delta_y = $this->vert_tick_increment;
|
|
} elseif ($this->num_vert_ticks) {
|
|
$delta_y = ($this->plot_max_y - $this->plot_min_y) / $this->num_vert_ticks;
|
|
} else {
|
|
$delta_y =($this->plot_max_y - $this->plot_min_y) / 10 ;
|
|
}
|
|
|
|
$y_tmp = $this->plot_min_y;
|
|
SetType($y_tmp,'double');
|
|
if ($this->skip_bottom_tick == 1) {
|
|
$y_tmp += $delta_y;
|
|
}
|
|
|
|
while ($y_tmp <= $this->plot_max_y){
|
|
//For log plots:
|
|
if (($this->yscale_type == "log") && ($this->plot_min_y == 1) &&
|
|
($delta_y%10 == 0) && ($y_tmp == $this->plot_min_y)) {
|
|
$y_tmp = $y_tmp - 1; //Set first increment to 9 to get: 1,10,20,30,...
|
|
}
|
|
|
|
$ylab = $this->FormatYTickLabel($y_tmp);
|
|
|
|
$this->DrawVerticalTick($ylab,$y_tmp);
|
|
|
|
$y_tmp += $delta_y;
|
|
}
|
|
|
|
return true;
|
|
|
|
} // function DrawVerticalTicks
|
|
|
|
function SetTranslation() {
|
|
if ($this->xscale_type == "log") {
|
|
$this->xscale = ($this->plot_area_width)/(log10($this->plot_max_x) - log10($this->plot_min_x));
|
|
} else {
|
|
$this->xscale = ($this->plot_area_width)/($this->plot_max_x - $this->plot_min_x);
|
|
}
|
|
if ($this->yscale_type == "log") {
|
|
$this->yscale = ($this->plot_area_height)/(log10($this->plot_max_y) - log10($this->plot_min_y));
|
|
} else {
|
|
$this->yscale = ($this->plot_area_height)/($this->plot_max_y - $this->plot_min_y);
|
|
}
|
|
|
|
// GD defines x=0 at left and y=0 at TOP so -/+ respectively
|
|
if ($this->xscale_type == "log") {
|
|
$this->plot_origin_x = $this->plot_area[0] - ($this->xscale * log10($this->plot_min_x) );
|
|
} else {
|
|
$this->plot_origin_x = $this->plot_area[0] - ($this->xscale * $this->plot_min_x);
|
|
}
|
|
if ($this->yscale_type == "log") {
|
|
$this->plot_origin_y = $this->plot_area[3] + ($this->yscale * log10($this->plot_min_y));
|
|
} else {
|
|
$this->plot_origin_y = $this->plot_area[3] + ($this->yscale * $this->plot_min_y);
|
|
}
|
|
|
|
$this->scale_is_set = 1;
|
|
} // function SetTranslation
|
|
|
|
function xtr($x_world) {
|
|
//Translate world coordinates into pixel coordinates
|
|
//The pixel coordinates are those of the ENTIRE image, not just the plot_area
|
|
//$x_pixels = $this->x_left_margin + ($this->image_width - $this->x_tot_margin)*(($x_world - $this->plot_min_x) / ($this->plot_max_x - $this->plot_min_x)) ;
|
|
//which with a little bit of math reduces to ...
|
|
if ($this->xscale_type == "log") {
|
|
$x_pixels = $this->plot_origin_x + log10($x_world) * $this->xscale ;
|
|
} else {
|
|
$x_pixels = $this->plot_origin_x + $x_world * $this->xscale ;
|
|
}
|
|
return($x_pixels);
|
|
}
|
|
|
|
function ytr($y_world) {
|
|
// translate y world coord into pixel coord
|
|
if ($this->yscale_type == "log") {
|
|
$y_pixels = $this->plot_origin_y - log10($y_world) * $this->yscale ; //minus because GD defines y=0 at top. doh!
|
|
} else {
|
|
$y_pixels = $this->plot_origin_y - $y_world * $this->yscale ;
|
|
}
|
|
return ($y_pixels);
|
|
}
|
|
|
|
|
|
function DrawDataLabel($lab,$x_world,$y_world) {
|
|
//Depreciated. Use DrawText Instead.
|
|
//Data comes in in WORLD coordinates
|
|
//Draw data label near actual data point
|
|
//$y = $this->ytr($y_world) ; //in pixels
|
|
//$x = $this->xtr($x_world) ;
|
|
//$this->DrawText($which_font,$which_angle,$which_xpos,$which_ypos,$which_color,$which_size,$which_text,$which_halign='left');
|
|
if ($this->use_ttf) {
|
|
//ajjjo
|
|
$lab_size = $this->TTFBBoxSize($this->axis_ttffont_size, $this->x_datalabel_angle, $this->axis_ttffont, $lab); //An array
|
|
$y = $this->ytr($y_world) - $lab_size[1] ; //in pixels
|
|
$x = $this->xtr($x_world) - $lab_size[0]/2;
|
|
ImageTTFText($this->img, $this->axis_ttffont_size, $this->x_datalabel_angle, $x, $y, $this->ndx_text_color, $this->axis_ttffont, $lab);
|
|
} else {
|
|
$lab_size = array($this->small_font_width*StrLen($lab), $this->small_font_height*3);
|
|
if ($this->x_datalabel_angle == 90) {
|
|
$y = $this->ytr($y_world) - $this->small_font_width*StrLen($lab); //in pixels
|
|
$x = $this->xtr($x_world) - $this->small_font_height;
|
|
ImageStringUp($this->img, $this->small_font,$x, $y ,$lab, $this->ndx_text_color);
|
|
} else {
|
|
$y = $this->ytr($y_world) - $this->small_font_height; //in pixels
|
|
$x = $this->xtr($x_world) - ($this->small_font_width*StrLen($lab))/2;
|
|
ImageString($this->img, $this->small_font,$x, $y ,$lab, $this->ndx_text_color);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function DrawXDataLabel($xlab,$xpos) {
|
|
//xpos comes in in PIXELS not in world coordinates.
|
|
//Draw an x data label centered at xlab
|
|
if ($this->use_ttf) {
|
|
$xlab_size = $this->TTFBBoxSize($this->axis_ttffont_size,
|
|
$this->x_datalabel_angle, $this->axis_ttffont, $xlab); //An array
|
|
$y = $this->plot_area[3] + $xlab_size[1] + 4; //in pixels
|
|
$x = $xpos - $xlab_size[0]/2;
|
|
ImageTTFText($this->img, $this->axis_ttffont_size,
|
|
$this->x_datalabel_angle, $x, $y, $this->ndx_text_color, $this->axis_ttffont, $xlab);
|
|
} else {
|
|
$xlab_size = array(ImageFontWidth($this->axis_font)*StrLen($xlab), $this->small_font_height*3);
|
|
if ($this->x_datalabel_angle == 90) {
|
|
$y = $this->plot_area[3] + ImageFontWidth($this->axis_font)*StrLen($xlab); //in pixels
|
|
$x = $xpos - ($this->small_font_height);
|
|
ImageStringUp($this->img, $this->axis_font,$x, $y ,$xlab, $this->ndx_text_color);
|
|
} else {
|
|
$y = $this->plot_area[3] + ImageFontHeight($this->axis_font); //in pixels
|
|
$x = $xpos - (ImageFontWidth($this->axis_font)*StrLen($xlab))/2;
|
|
ImageString($this->img, $this->axis_font,$x, $y ,$xlab, $this->ndx_text_color);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function DrawPieChart() {
|
|
//$pi = '3.14159265358979323846';
|
|
$xpos = $this->plot_area[0] + $this->plot_area_width/2;
|
|
$ypos = $this->plot_area[1] + $this->plot_area_height/2;
|
|
$diameter = (min($this->plot_area_width, $this->plot_area_height)) ;
|
|
$radius = $diameter/2;
|
|
|
|
ImageArc($this->img, $xpos, $ypos, $diameter, $diameter, 0, 360, $this->ndx_grid_color);
|
|
|
|
$total = 0;
|
|
reset($this->data_values);
|
|
$tmp = $this->number_x_points - 1;
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
//Get sum of each type
|
|
$color_index = 0;
|
|
$i = 0;
|
|
//foreach ($row as $v)
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k != 0) {
|
|
if ($j == 0) {
|
|
$sumarr[$i] = $v;
|
|
} elseif ($j < $tmp) {
|
|
$sumarr[$i] += $v;
|
|
} else {
|
|
$sumarr[$i] += $v;
|
|
// NOTE! sum > 0 to make pie charts
|
|
$sumarr[$i] = abs($sumarr[$i]);
|
|
$total += $sumarr[$i];
|
|
}
|
|
}
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
$color_index = 0;
|
|
$start_angle = 0;
|
|
|
|
reset($sumarr);
|
|
$end_angle = 0;
|
|
while (list(, $val) = each($sumarr)) {
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0; //data_color = array
|
|
$label_txt = number_format(($val / $total * 100), $this->y_precision, ".", ",") . "%";
|
|
$val = 360 * ($val / $total);
|
|
|
|
$end_angle += $val;
|
|
$mid_angle = $end_angle - ($val / 2);
|
|
|
|
$slicecol = $this->ndx_data_color[$color_index];
|
|
|
|
//Need this again for FillToBorder
|
|
ImageArc($this->img, $xpos, $ypos, $diameter, $diameter, 0, 360, $this->ndx_grid_color);
|
|
|
|
$out_x = $radius * cos(deg2rad($end_angle));
|
|
$out_y = - $radius * sin(deg2rad($end_angle));
|
|
|
|
$mid_x = $xpos + ($radius/2 * cos(deg2rad($mid_angle))) ;
|
|
$mid_y = $ypos + (- $radius/2 * sin(deg2rad($mid_angle)));
|
|
|
|
$label_x = $xpos + ($radius * cos(deg2rad($mid_angle))) * $this->label_scale_position;
|
|
$label_y = $ypos + (- $radius * sin(deg2rad($mid_angle))) * $this->label_scale_position;
|
|
|
|
$out_x = $xpos + $out_x;
|
|
$out_y = $ypos + $out_y;
|
|
|
|
ImageLine($this->img, $xpos, $ypos, $out_x, $out_y, $this->ndx_grid_color);
|
|
//ImageLine($this->img, $xpos, $ypos, $label_x, $label_y, $this->ndx_grid_color);
|
|
ImageFillToBorder($this->img, $mid_x, $mid_y, $this->ndx_grid_color, $slicecol);
|
|
|
|
if ($this->use_ttf) {
|
|
ImageTTFText($this->img, $this->axis_ttffont_size, 0, $label_x, $label_y, $this->ndx_grid_color, $this->axis_ttffont, $label_txt);
|
|
} else {
|
|
ImageString($this->img, $this->small_font, $label_x, $label_y, $label_txt, $this->ndx_grid_color);
|
|
}
|
|
|
|
$start_angle = $val;
|
|
|
|
$color_index++;
|
|
}
|
|
|
|
}
|
|
|
|
function DrawLinesError() {
|
|
//Draw Lines with Error Bars - data comes in as array("title",x,y,error+,error-,y2,error2+,error2-,...);
|
|
$start_lines = 0;
|
|
|
|
reset($this->data_values);
|
|
while (list(, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
$i = 0;
|
|
|
|
while (list($key, $val) = each($row)) {
|
|
//echo "$key, $i, $val<br>";
|
|
if ($key == 0) {
|
|
$lab = $val;
|
|
} elseif ($key == 1) {
|
|
$x_now = $val;
|
|
$x_now_pixels = $this->xtr($x_now); //Use a bit more memory to save 2N operations.
|
|
} elseif ($key%3 == 2) {
|
|
$y_now = $val;
|
|
$y_now_pixels = $this->ytr($y_now);
|
|
|
|
//Draw Data Label
|
|
if ( $this->draw_data_labels == 1) {
|
|
$this->DrawDataLabel($lab,$x_now,$y_now);
|
|
}
|
|
|
|
if ($color_index >= count($this->ndx_data_color)) { $color_index=0;};
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
$error_barcol = $this->ndx_error_bar_color[$color_index];
|
|
|
|
//echo "start = $start_lines<br>";
|
|
if ($start_lines == 1) {
|
|
for ($width = 0; $width < $this->line_width; $width++) {
|
|
ImageLine($this->img, $x_now_pixels, $y_now_pixels + $width,
|
|
$lastx[$i], $lasty[$i] + $width, $barcol);
|
|
}
|
|
}
|
|
|
|
$lastx[$i] = $x_now_pixels;
|
|
$lasty[$i] = $y_now_pixels;
|
|
$color_index++;
|
|
$i++;
|
|
$start_lines = 1;
|
|
} elseif ($key%3 == 0) {
|
|
$this->DrawYErrorBar($x_now,$y_now,$val,$this->error_bar_shape,$error_barcol);
|
|
} elseif ($key%3 == 1) {
|
|
$this->DrawYErrorBar($x_now,$y_now,-$val,$this->error_bar_shape,$error_barcol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function DrawDotsError() {
|
|
//Draw Dots - data comes in as array("title",x,y,error+,error-,y2,error2+,error2-,...);
|
|
reset($this->data_values);
|
|
while (list(, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
//foreach ($row as $v)
|
|
while (list($key, $val) = each($row)) {
|
|
if ($key == 0) {
|
|
} elseif ($key == 1) {
|
|
$xpos = $val;
|
|
} elseif ($key%3 == 2) {
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
$error_barcol = $this->ndx_error_bar_color[$color_index];
|
|
$ypos = $val;
|
|
|
|
$color_index++;
|
|
$this->DrawDot($xpos,$ypos,$this->point_shape,$barcol);
|
|
} elseif ($key%3 == 0) {
|
|
$this->DrawYErrorBar($xpos,$ypos,$val,$this->error_bar_shape,$error_barcol);
|
|
} elseif ($key%3 == 1) {
|
|
$mine = $val ;
|
|
$this->DrawYErrorBar($xpos,$ypos,-$val,$this->error_bar_shape,$error_barcol);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function DrawDots() {
|
|
//Draw Dots - data comes in as array("title",x,y1,y2,y3,...);
|
|
reset($this->data_values);
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
//foreach ($row as $v)
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
} elseif (($k == 1) && ($this->data_type == "data-data")) {
|
|
$xpos = $v;
|
|
} else {
|
|
if ($this->data_type == "text-data") {
|
|
$xpos = ($j+.5);
|
|
}
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
|
|
//if (is_numeric($v)) //PHP4 only
|
|
if ((strval($v) != "") ) { //Allow for missing Y data
|
|
$this->DrawDot($xpos,$v,$this->point_shape,$barcol);
|
|
}
|
|
$color_index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
} //function DrawDots
|
|
|
|
function DrawDotSeries() {
|
|
//Depreciated: Use DrawDots
|
|
$this->DrawDots();
|
|
}
|
|
|
|
function DrawThinBarLines() {
|
|
//A clean,fast routine for when you just want charts like stock volume charts
|
|
//Data must be text-data since I didn't see a graphing need for equally spaced thin lines.
|
|
//If you want it - then write to afan@jeo.net and I might add it.
|
|
|
|
if ($this->data_type != "data-data") { $this->DrawError('Data Type for ThinBarLines must be data-data'); };
|
|
$y1 = $this->ytr($this->x_axis_position);
|
|
|
|
reset($this->data_values);
|
|
while (list(, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
$xlab = $v;
|
|
} elseif ($k == 1) {
|
|
$xpos = $this->xtr($v);
|
|
if ( ($this->draw_x_data_labels == 1) ) { //See "labels_note1 above.
|
|
$this->DrawXDataLabel($xlab,$xpos);
|
|
}
|
|
} else {
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
|
|
ImageLine($this->img,$xpos,$y1,$xpos,$this->ytr($v),$barcol);
|
|
$color_index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
} //function DrawThinBarLines
|
|
|
|
function DrawYErrorBar($x_world,$y_world,$error_height,$error_bar_type,$color) {
|
|
$x1 = $this->xtr($x_world);
|
|
$y1 = $this->ytr($y_world);
|
|
$y2 = $this->ytr($y_world+$error_height) ;
|
|
|
|
for ($width = 0; $width < $this->error_bar_line_width; $width++) {
|
|
ImageLine($this->img, $x1+$width, $y1 , $x1+$width, $y2, $color);
|
|
ImageLine($this->img, $x1-$width, $y1 , $x1-$width, $y2, $color);
|
|
}
|
|
switch ($error_bar_type) {
|
|
case "line":
|
|
break;
|
|
case "tee":
|
|
ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
|
|
break;
|
|
default:
|
|
ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawDot($x_world,$y_world,$dot_type,$color) {
|
|
$half_point = $this->point_size / 2;
|
|
$x1 = $this->xtr($x_world) - $half_point;
|
|
$x2 = $this->xtr($x_world) + $half_point;
|
|
$y1 = $this->ytr($y_world) - $half_point;
|
|
$y2 = $this->ytr($y_world) + $half_point;
|
|
|
|
switch ($dot_type) {
|
|
case "halfline":
|
|
ImageFilledRectangle($this->img, $x1, $this->ytr($y_world), $this->xtr($x_world), $this->ytr($y_world), $color);
|
|
break;
|
|
case "line":
|
|
ImageFilledRectangle($this->img, $x1, $this->ytr($y_world), $x2, $this->ytr($y_world), $color);
|
|
break;
|
|
case "rect":
|
|
ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
|
|
break;
|
|
case "circle":
|
|
ImageArc($this->img, $x1 + $half_point, $y1 + $half_point, $this->point_size, $this->point_size, 0, 360, $color);
|
|
break;
|
|
case "dot":
|
|
ImageArc($this->img, $x1 + $half_point, $y1 + $half_point, $this->point_size, $this->point_size, 0, 360, $color);
|
|
ImageFillToBorder($this->img, $x1 + $half_point, $y1 + $half_point, $color, $color);
|
|
break;
|
|
case "diamond":
|
|
|
|
$arrpoints = array(
|
|
$x1,$y1 + $half_point,
|
|
$x1 + $half_point, $y1,
|
|
$x2,$y1 + $half_point,
|
|
$x1 + $half_point, $y2
|
|
);
|
|
|
|
ImageFilledPolygon($this->img, $arrpoints, 4, $color);
|
|
break;
|
|
case "triangle":
|
|
$arrpoints = array( $x1, $y1 + $half_point,
|
|
$x2, $y1 + $half_point,
|
|
$x1 + $half_point, $y2
|
|
);
|
|
ImageFilledPolygon($this->img, $arrpoints, 3, $color);
|
|
break;
|
|
default:
|
|
ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function SetErrorBarLineWidth($which_seblw) {
|
|
$this->error_bar_line_width = $which_seblw;
|
|
return true;
|
|
}
|
|
|
|
|
|
function SetLineWidth($which_lw) {
|
|
$this->line_width = $which_lw;
|
|
if (!$this->error_bar_line_width) {
|
|
$this->error_bar_line_width = $which_lw;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function DrawArea() {
|
|
//Data comes in as $data[]=("title",x,y,...);
|
|
//Set first and last datapoints of area
|
|
$i = 0;
|
|
while ($i < $this->records_per_group) {
|
|
$posarr[$i][] = $this->xtr($this->min_x); //x initial
|
|
$posarr[$i][] = $this->ytr($this->x_axis_position); //y initial
|
|
$i++;
|
|
}
|
|
|
|
reset($this->data_values);
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
//foreach ($row as $v)
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
//Draw Data Labels
|
|
$xlab = SubStr($v,0,$this->x_datalabel_maxlength);
|
|
} elseif ($k == 1) {
|
|
$x = $this->xtr($v);
|
|
// DrawXDataLabel interferes with Numbers on x-axis
|
|
//$this->DrawXDataLabel($xlab,$x);
|
|
} else {
|
|
// Create Array of points for later
|
|
|
|
$y = $this->ytr($v);
|
|
$posarr[$color_index][] = $x;
|
|
$posarr[$color_index][] = $y;
|
|
$color_index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Final_points
|
|
for ($i = 0; $i < $this->records_per_group; $i++) {
|
|
$posarr[$i][] = $this->xtr($this->max_x); //x final
|
|
$posarr[$i][] = $this->ytr($this->x_axis_position); //y final
|
|
}
|
|
|
|
$color_index=0;
|
|
|
|
//foreach($posarr as $row)
|
|
reset($posarr);
|
|
while (list(, $row) = each($posarr)) {
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
//echo "$row[0],$row[1],$row[2],$row[3],$row[4],$row[5],$row[6],$row[7],$row[8],$row[9],$row[10],$row[11],$row[12], $barcol<br>";
|
|
ImageFilledPolygon($this->img, $row, (count($row)) / 2, $barcol);
|
|
$color_index++;
|
|
}
|
|
//exit;
|
|
|
|
}
|
|
|
|
function DrawAreaSeries() {
|
|
|
|
//Set first and last datapoints of area
|
|
$i = 0;
|
|
while ($i < $this->records_per_group) {
|
|
$posarr[$i][] = $this->xtr(.5); //x initial
|
|
$posarr[$i][] = $this->ytr($this->x_axis_position); //y initial
|
|
$i++;
|
|
}
|
|
|
|
reset($this->data_values);
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
$color_index = 0;
|
|
//foreach ($row as $v)
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
//Draw Data Labels
|
|
$xlab = SubStr($v,0,$this->x_datalabel_maxlength);
|
|
$this->DrawXDataLabel($xlab,$this->xtr($j + .5));
|
|
} else {
|
|
// Create Array of points for later
|
|
|
|
$x = round($this->xtr($j + .5 ));
|
|
$y = round($this->ytr($v));
|
|
$posarr[$color_index][] = $x;
|
|
$posarr[$color_index][] = $y;
|
|
$color_index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Final_points
|
|
for ($i = 0; $i < $this->records_per_group; $i++) {
|
|
$posarr[$i][] = round($this->xtr($this->max_x + .5)); //x final
|
|
$posarr[$i][] = $this->ytr($this->x_axis_position); //y final
|
|
}
|
|
|
|
$color_index=0;
|
|
|
|
//foreach($posarr as $row)
|
|
reset($posarr);
|
|
while (list(, $row) = each($posarr)) {
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
//echo "$row[0],$row[1],$row[2],$row[3],$row[4],$row[5],$row[6],$row[7],$row[8],$row[9],$row[10],$row[11],$row[12], $barcol<br>";
|
|
ImageFilledPolygon($this->img, $row, (count($row)) / 2, $barcol);
|
|
$color_index++;
|
|
}
|
|
|
|
}
|
|
|
|
function DrawLines() {
|
|
//Data comes in as $data[]=("title",x,y,...);
|
|
$start_lines = 0;
|
|
if ($this->data_type == "text-data") {
|
|
$lastx[0] = $this->xtr(0);
|
|
$lasty[0] = $this->xtr(0);
|
|
}
|
|
|
|
//foreach ($this->data_values as $row)
|
|
reset($this->data_values);
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
|
|
$color_index = 0;
|
|
$i = 0;
|
|
//foreach ($row as $v)
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
$xlab = SubStr($v,0,$this->x_datalabel_maxlength);
|
|
} elseif (($k == 1) && ($this->data_type == "data-data")) {
|
|
$x_now = $this->xtr($v);
|
|
} else {
|
|
//(double) $v;
|
|
// Draw Lines
|
|
if ($this->data_type == "text-data") {
|
|
$x_now = $this->xtr($j+.5);
|
|
}
|
|
|
|
//if (is_numeric($v)) //PHP4 only
|
|
if ((strval($v) != "") ) { //Allow for missing Y data
|
|
$y_now = $this->ytr($v);
|
|
if ($color_index >= count($this->ndx_data_color)) { $color_index=0;} ;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
|
|
if ($start_lines == 1) {
|
|
for ($width = 0; $width < $this->line_width; $width++) {
|
|
if ($this->line_style[$i] == "dashed") {
|
|
$this->DrawDashedLine($x_now, $y_now + $width, $lastx[$i], $lasty[$i] + $width, 4,4, $barcol);
|
|
} else {
|
|
ImageLine($this->img, $x_now, $y_now + $width, $lastx[$i], $lasty[$i] + $width, $barcol);
|
|
}
|
|
}
|
|
}
|
|
$lastx[$i] = $x_now;
|
|
} else {
|
|
$y_now = $lasty[$i];
|
|
//Don't increment lastx[$i]
|
|
}
|
|
//$bordercol = $this->ndx_data_border_color[$colbarcount];
|
|
|
|
$lasty[$i] = $y_now;
|
|
$color_index++;
|
|
$i++;
|
|
}
|
|
//Now we are assured an x_value
|
|
if ( ($this->draw_x_data_labels == 1) && ($k == 1) ) { //See "labels_note1 above.
|
|
$this->DrawXDataLabel($xlab,$x_now);
|
|
}
|
|
} //while rows of data
|
|
$start_lines = 1;
|
|
}
|
|
}
|
|
|
|
//Data comes in as $data[]=("title",x,y,e+,e-,y2,e2+,e2-,...);
|
|
|
|
function DrawLineSeries() {
|
|
//This function is replaced by DrawLines
|
|
//Tests have shown not much improvement in speed by having separate routines for DrawLineSeries and DrawLines
|
|
//For ease of programming I have combined them
|
|
return false;
|
|
} //function DrawLineSeries
|
|
|
|
function DrawDashedLine($x1pix,$y1pix,$x2pix,$y2pix,$dash_length,$dash_space,$color) {
|
|
//Code based on work by Ariel Garza and James Pine
|
|
//I've decided to have this be in pixels only as a replacement for ImageLine
|
|
//$x1pix = $this->xtr($x1);
|
|
//$y1pix = $this->ytr($y1);
|
|
//$x2pix = $this->xtr($x2);
|
|
//$y2pix = $this->ytr($y2);
|
|
|
|
// Get the length of the line in pixels
|
|
$line_length = ceil (sqrt(pow(($x2pix - $x1pix),2) + pow(($y2pix - $y1pix),2)) );
|
|
|
|
$dx = ($x2pix - $x1pix) / $line_length;
|
|
$dy = ($y2pix - $y1pix) / $line_length;
|
|
$lastx = $x1pix;
|
|
$lasty = $y1pix;
|
|
|
|
// Draw the dashed line
|
|
for ($i = 0; $i < $line_length; $i += ($dash_length + $dash_space)) {
|
|
$xpix = ($dash_length * $dx) + $lastx;
|
|
$ypix = ($dash_length * $dy) + $lasty;
|
|
|
|
ImageLine($this->img,$lastx,$lasty,$xpix,$ypix,$color);
|
|
$lastx = $xpix + ($dash_space * $dx);
|
|
$lasty = $ypix + ($dash_space * $dy);
|
|
}
|
|
} // function DrawDashedLine
|
|
|
|
function DrawBars() {
|
|
|
|
if ($this->data_type != "text-data") {
|
|
$this->DrawError('Bar plots must be text-data: use function SetDataType("text-data")');
|
|
}
|
|
|
|
$xadjust = ($this->records_per_group * $this->record_bar_width )/4;
|
|
|
|
reset($this->data_values);
|
|
while (list($j, $row) = each($this->data_values)) {
|
|
|
|
$color_index = 0;
|
|
$colbarcount = 0;
|
|
$x_now = $this->xtr($j+.5);
|
|
|
|
while (list($k, $v) = each($row)) {
|
|
if ($k == 0) {
|
|
//Draw Data Labels
|
|
$xlab = SubStr($v,0,$this->x_datalabel_maxlength);
|
|
$this->DrawXDataLabel($xlab,$x_now);
|
|
} else {
|
|
// Draw Bars ($v)
|
|
$x1 = $x_now - $this->data_group_space + ($k-1)*$this->record_bar_width;
|
|
$x2 = $x1 + $this->record_bar_width*$this->bar_width_adjust;
|
|
|
|
if ($v < $this->x_axis_position) {
|
|
$y1 = $this->ytr($this->x_axis_position);
|
|
$y2 = $this->ytr($v);
|
|
} else {
|
|
$y1 = $this->ytr($v);
|
|
$y2 = $this->ytr($this->x_axis_position);
|
|
}
|
|
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
if ($colbarcount >= count($this->ndx_data_border_color)) $colbarcount=0;
|
|
$barcol = $this->ndx_data_color[$color_index];
|
|
$bordercol = $this->ndx_data_border_color[$colbarcount];
|
|
|
|
if ((strval($v) != "") ) { //Allow for missing Y data
|
|
if ($this->shading > 0) {
|
|
for($i=0;$i<($this->shading);$i++) {
|
|
//Shading set in SetDefaultColors
|
|
ImageFilledRectangle($this->img, $x1+$i, $y1-$i, $x2+$i, $y2-$i, $this->ndx_i_light);
|
|
}
|
|
}
|
|
|
|
ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $barcol);
|
|
ImageRectangle($this->img, $x1, $y1, $x2, $y2, $bordercol);
|
|
if ($this->draw_data_labels == '1') { //ajo
|
|
$y1 = $this->ytr($this->label_scale_position * $v);
|
|
//$this->DrawDataLabel($v,$j + .5,$v*$this->label_scale_position);
|
|
$this->DrawText($this->x_label_ttffont, $this->x_label_angle,
|
|
$x1+$this->record_bar_width/2, $y1, $this->ndx_label_color, $this->x_label_ttffont_size, $v,'center','top');
|
|
}
|
|
}
|
|
|
|
$color_index++;
|
|
$colbarcount++;
|
|
}
|
|
}
|
|
}
|
|
} //function DrawBars
|
|
|
|
function DrawLegend($which_x1,$which_y1,$which_boxtype) {
|
|
//Base code submitted by Marlin Viss
|
|
$max_legend_length=0;
|
|
reset($this->legend);
|
|
while (list(,$leg) = each($this->legend)) {
|
|
$len = strlen($leg);
|
|
if ($max_legend_length < $len) {
|
|
$max_legend_length = $len;
|
|
}
|
|
}
|
|
|
|
$line_spacing = 1.25;
|
|
$vert_margin = $this->small_font_height/2 ;
|
|
$dot_height = $this->small_font_height*$line_spacing - 1;
|
|
|
|
//Upper Left
|
|
if ((!$which_x1) || (!$which_y1) ) {
|
|
$box_start_x = $this->plot_area[2] - $this->small_font_width*($max_legend_length+4);
|
|
$box_start_y = $this->plot_area[1] + 4;
|
|
} else {
|
|
$box_start_x = $which_x1;
|
|
$box_start_y = $which_y1;
|
|
}
|
|
|
|
//Lower Right
|
|
$box_end_y = $box_start_y + $this->small_font_height*(count($this->legend)+1) + 2*$vert_margin;
|
|
//$box_end_x = $this->plot_area[2] - 5;
|
|
$box_end_x = $box_start_x + $this->small_font_width*($max_legend_length+4) - 5;
|
|
|
|
|
|
// Draw box for legend
|
|
ImageFilledRectangle($this->img,
|
|
$box_start_x, $box_start_y,$box_end_x,
|
|
$box_end_y, $this->ndx_bg_color);
|
|
ImageRectangle($this->img,
|
|
$box_start_x, $box_start_y,$box_end_x,
|
|
$box_end_y, $this->ndx_grid_color);
|
|
|
|
$color_index=0;
|
|
$i = 0;
|
|
|
|
|
|
reset($this->legend);
|
|
|
|
|
|
while (list(,$leg) = each($this->legend)) {
|
|
$y_pos = $box_start_y + $this->small_font_height*($i)*($line_spacing) + $vert_margin;
|
|
|
|
ImageString($this->img, $this->small_font,
|
|
$box_start_x + $this->small_font_width*( $max_legend_length - strlen($leg) + 1 ) ,
|
|
$y_pos,
|
|
$leg, $this->ndx_text_color);
|
|
|
|
if ($color_index >= count($this->ndx_data_color)) $color_index=0;
|
|
// Draw a box in the data color
|
|
ImageFilledRectangle($this->img,
|
|
$box_end_x - $this->small_font_width*2,
|
|
$y_pos + 1, $box_end_x - $this->small_font_width,
|
|
$y_pos + $dot_height,
|
|
$this->ndx_data_color[$color_index]);
|
|
|
|
ImageRectangle($this->img,
|
|
$box_end_x - $this->small_font_width*2,
|
|
$y_pos + 1, $box_end_x - $this->small_font_width,
|
|
$y_pos + $dot_height,
|
|
$this->ndx_text_color);
|
|
$i++;
|
|
$color_index++;
|
|
}
|
|
} //function DrawLegend
|
|
|
|
|
|
function DrawGraph() {
|
|
|
|
if (($this->img) == "") {
|
|
$this->DrawError('No Image Defined: DrawGraph');
|
|
//$this->PHPlot();
|
|
}
|
|
|
|
if (! is_array($this->data_values)) {
|
|
$this->DrawBackground();
|
|
$this->DrawError("No array of data in \$data_values");
|
|
} else {
|
|
if (!$this->data_color) {
|
|
$this->SetDataColors(array('blue','green','yellow','red','orange','blue'),array('black'));
|
|
}
|
|
|
|
$this->FindDataLimits(); //Get maxima and minima for scaling
|
|
|
|
$this->SetXLabelHeight(); //Get data for bottom margin
|
|
|
|
$this->SetYLabelWidth(); //Get data for left margin
|
|
|
|
if (!$this->plot_area_width) {
|
|
$this->SetPlotAreaPixels('','','',''); //Set Margins
|
|
}
|
|
|
|
if (!$this->plot_max_y) { //If not set by user call SetPlotAreaWorld,
|
|
$this->SetPlotAreaWorld('','','','');
|
|
}
|
|
|
|
if ($this->data_type == "text-data") {
|
|
$this->SetEqualXCoord();
|
|
}
|
|
|
|
$this->SetPointSize($this->point_size);
|
|
|
|
$this->DrawBackground();
|
|
$this->DrawImageBorder();
|
|
|
|
$this->SetTranslation();
|
|
|
|
if ($this->draw_plot_area_background == 1) {
|
|
$this->DrawPlotAreaBackground();
|
|
}
|
|
//$foo = "$this->max_y, $this->min_y, $new_miny, $new_maxy, $this->x_label_height";
|
|
//ImageString($this->img, 4, 20, 20, $foo, $this->ndx_text_color);
|
|
|
|
switch ($this->plot_type) {
|
|
case "bars":
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
$this->DrawBars();
|
|
$this->DrawXAxis();
|
|
break;
|
|
case "thinbarline":
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
$this->DrawThinBarLines();
|
|
break;
|
|
case "lines":
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
if ( $this->data_type == "text-data") {
|
|
$this->DrawLines();
|
|
} elseif ( $this->data_type == "data-data-error") {
|
|
$this->DrawLinesError();
|
|
} else {
|
|
$this->DrawLines();
|
|
}
|
|
break;
|
|
case "area":
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
if ( $this->data_type == "text-data") {
|
|
$this->DrawAreaSeries();
|
|
} else {
|
|
$this->DrawArea();
|
|
}
|
|
break;
|
|
case "linepoints":
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
if ( $this->data_type == "text-data") {
|
|
$this->DrawLines();
|
|
$this->DrawDots();
|
|
} elseif ( $this->data_type == "data-data-error") {
|
|
$this->DrawLinesError();
|
|
$this->DrawDotsError();
|
|
} else {
|
|
$this->DrawLines();
|
|
$this->DrawDots();
|
|
}
|
|
break;
|
|
case "points";
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
if ( $this->data_type == "text-data") {
|
|
$this->DrawDots();
|
|
} elseif ( $this->data_type == "data-data-error") {
|
|
$this->DrawDotsError();
|
|
} else {
|
|
$this->DrawDots();
|
|
}
|
|
break;
|
|
case "pie":
|
|
$this->DrawPieChart();
|
|
$this->DrawLabels();
|
|
break;
|
|
default:
|
|
$this->DrawPlotBorder();
|
|
$this->DrawLabels();
|
|
$this->DrawBars();
|
|
break;
|
|
}
|
|
|
|
if ($this->legend) {
|
|
$this->DrawLegend($this->legend_x_pos,$this->legend_y_pos,'');
|
|
}
|
|
|
|
}
|
|
if ($this->print_image == 1) {
|
|
$this->PrintImage();
|
|
}
|
|
} //function DrawGraph
|
|
|
|
}
|
|
|
|
// $graph = new PHPlot;
|
|
|
|
// $graph->DrawGraph();
|
|
|
|
?>
|