linea21-externals
[ class tree: linea21-externals ] [ index: linea21-externals ] [ all elements ]

Source for file Plot.class.php

Documentation is available at Plot.class.php

  1. <?php
  2. /*
  3.  * This work is hereby released into the Public Domain.
  4.  * To view a copy of the public domain dedication,
  5.  * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
  6.  * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
  7.  *
  8.  */
  9.  
  10. require_once dirname(__FILE__)."/Component.class.php";
  11.  
  12. /* <php4> */
  13.  
  14. define("PLOT_LEFT", 'left');
  15. define("PLOT_RIGHT", 'right');
  16. define("PLOT_TOP", 'top');
  17. define("PLOT_BOTTOM", 'bottom');
  18. define("PLOT_BOTH", 'both');
  19.  
  20. /* </php4> */
  21.  
  22. /**
  23.  * Graph using X and Y axis
  24.  *
  25.  * @package linea21.externals
  26.  * @subpackage artichow
  27.  */
  28. class awPlot extends awComponent {
  29.  
  30.   /**
  31.    * Values for Y axis
  32.    *
  33.    * @var array 
  34.    */
  35.   var $datay;
  36.  
  37.   /**
  38.    * Values for X axis
  39.    *
  40.    * @var array 
  41.    */
  42.   var $datax;
  43.  
  44.   /**
  45.    * Grid properties
  46.    *
  47.    * @var Grid 
  48.    */
  49.   var $grid;
  50.  
  51.   /**
  52.    * X axis
  53.    *
  54.    * @var Axis 
  55.    */
  56.   var $xAxis;
  57.  
  58.   /**
  59.    * Y axis
  60.    *
  61.    * @var Axis 
  62.    */
  63.   var $yAxis;
  64.  
  65.   /**
  66.    * Position of X axis
  67.    *
  68.    * @var int 
  69.    */
  70.   var $xAxisPosition = PLOT_BOTTOM;
  71.  
  72.   /**
  73.    * Set X axis on zero ?
  74.    *
  75.    * @var bool 
  76.    */
  77.   var $xAxisZero = TRUE;
  78.  
  79.   /**
  80.    * Set Y axis on zero ?
  81.    *
  82.    * @var bool 
  83.    */
  84.   var $yAxisZero = FALSE;
  85.  
  86.   /**
  87.    * Position of Y axis
  88.    *
  89.    * @var int 
  90.    */
  91.   var $yAxisPosition = PLOT_LEFT;
  92.  
  93.   /**
  94.    * Change min value for Y axis
  95.    *
  96.    * @var mixed 
  97.    */
  98.   var $yMin = NULL;
  99.  
  100.   /**
  101.    * Change max value for Y axis
  102.    *
  103.    * @var mixed 
  104.    */
  105.   var $yMax = NULL;
  106.  
  107.   /**
  108.    * Change min value for X axis
  109.    *
  110.    * @var mixed 
  111.    */
  112.   var $xMin = NULL;
  113.  
  114.   /**
  115.    * Change max value for X axis
  116.    *
  117.    * @var mixed 
  118.    */
  119.   var $xMax = NULL;
  120.  
  121.   /**
  122.    * Left axis
  123.    *
  124.    * @var int 
  125.    */
  126.  
  127.  
  128.   /**
  129.    * Right axis
  130.    *
  131.    * @var int 
  132.    */
  133.  
  134.  
  135.   /**
  136.    * Top axis
  137.    *
  138.    * @var int 
  139.    */
  140.  
  141.  
  142.   /**
  143.    * Bottom axis
  144.    *
  145.    * @var int 
  146.    */
  147.  
  148.  
  149.   /**
  150.    * Both left/right or top/bottom axis
  151.    *
  152.    * @var int 
  153.    */
  154.  
  155.  
  156.   /**
  157.    * Build the plot
  158.    *
  159.    */
  160.   function awPlot() {
  161.  
  162.     parent::awComponent();
  163.  
  164.     $this->grid = new awGrid;
  165.     $this->grid->setBackgroundColor(new awWhite);
  166.  
  167.     $this->padding->add(20, 0, 0, 20);
  168.  
  169.     $this->xAxis = new awAxis;
  170.     $this->xAxis->addTick('major', new awTick(0, 5));
  171.     $this->xAxis->addTick('minor', new awTick(0, 3));
  172.     $this->xAxis->setTickStyle(TICK_OUT);
  173.     $this->xAxis->label->setFont(new awTuffy(7));
  174.  
  175.     $this->yAxis = new awAxis;
  176.     $this->yAxis->auto(TRUE);
  177.     $this->yAxis->addTick('major', new awTick(0, 5));
  178.     $this->yAxis->addTick('minor', new awTick(0, 3));
  179.     $this->yAxis->setTickStyle(TICK_OUT);
  180.     $this->yAxis->setNumberByTick('minor', 'major', 3);
  181.     $this->yAxis->label->setFont(new awTuffy(7));
  182.     $this->yAxis->title->setAngle(90);
  183.  
  184.   }
  185.  
  186.   /**
  187.    * Get plot values
  188.    *
  189.    * @return array 
  190.    */
  191.   function getValues() {
  192.     return $this->datay;
  193.   }
  194.  
  195.   /**
  196.    * Reduce number of values in the plot
  197.    *
  198.    * @param int $number Reduce number of values to $number
  199.    */
  200.   function reduce($number) {
  201.  
  202.     $count = count($this->datay);
  203.     $ratio = ceil($count / $number);
  204.  
  205.     if($ratio > 1) {
  206.  
  207.       $tmpy = $this->datay;
  208.       $datay = array();
  209.           
  210.       $datax = array();
  211.       $cbLabel = $this->xAxis->label->getCallbackFunction();
  212.           
  213.       for($i = 0; $i < $count; $i += $ratio) {
  214.             
  215.         $slice = array_slice($tmpy, $i, $ratio);
  216.         $datay[] = array_sum($slice) / count($slice);
  217.  
  218.         // Reduce data on X axis if needed
  219.         if($cbLabel !== NULL) {
  220.           $datax[] = $cbLabel($i + round($ratio / 2));
  221.         }
  222.  
  223.       }
  224.           
  225.       $this->setValues($datay);
  226.           
  227.       if($cbLabel !== NULL) {
  228.         $this->xAxis->setLabelText($datax);
  229.       }
  230.           
  231.           
  232.     }
  233.  
  234.   }
  235.  
  236.   /**
  237.    * Count values in the plot
  238.    *
  239.    * @return int 
  240.    */
  241.   function getXAxisNumber() {
  242.     list($min, $max) = $this->xAxis->getRange();
  243.     return ($max - $min + 1);
  244.   }
  245.  
  246.   /**
  247.    * Change X axis
  248.    *
  249.    * @param int $axis 
  250.    */
  251.   function setXAxis($axis) {
  252.     $this->xAxisPosition = $axis;
  253.   }
  254.  
  255.   /**
  256.    * Get X axis
  257.    *
  258.    * @return int 
  259.    */
  260.   function getXAxis() {
  261.     return $this->xAxisPosition;
  262.   }
  263.  
  264.   /**
  265.    * Set X axis on zero
  266.    *
  267.    * @param bool $zero 
  268.    */
  269.   function setXAxisZero($zero) {
  270.     $this->xAxisZero = (bool)$zero;
  271.   }
  272.  
  273.   /**
  274.    * Set Y axis on zero
  275.    *
  276.    * @param bool $zero 
  277.    */
  278.   function setYAxisZero($zero) {
  279.     $this->yAxisZero = (bool)$zero;
  280.   }
  281.  
  282.   /**
  283.    * Change Y axis
  284.    *
  285.    * @param int $axis 
  286.    */
  287.   function setYAxis($axis) {
  288.     $this->yAxisPosition = $axis;
  289.   }
  290.  
  291.   /**
  292.    * Get Y axis
  293.    *
  294.    * @return int 
  295.    */
  296.   function getYAxis() {
  297.     return $this->yAxisPosition;
  298.   }
  299.  
  300.   /**
  301.    * Change min value for Y axis
  302.    * Set NULL for auto selection.
  303.    *
  304.    * @param float $value 
  305.    */
  306.   function setYMin($value) {
  307.     $this->yMin = $value;
  308.     $this->yAxis->auto(FALSE);
  309.     $this->updateAxis();
  310.   }
  311.  
  312.   /**
  313.    * Change max value for Y axis
  314.    * Set NULL for auto selection.
  315.    *
  316.    * @param float $value 
  317.    */
  318.   function setYMax($value) {
  319.     $this->yMax = $value;
  320.     $this->yAxis->auto(FALSE);
  321.     $this->updateAxis();
  322.   }
  323.  
  324.   /**
  325.    * Change min value for X axis
  326.    * Set NULL for auto selection.
  327.    *
  328.    * @param float $value 
  329.    */
  330.   function setXMin($value) {
  331.     $this->xMin = $value;
  332.     $this->updateAxis();
  333.   }
  334.  
  335.   /**
  336.    * Change max value for X axis
  337.    * Set NULL for auto selection.
  338.    *
  339.    * @param float $value 
  340.    */
  341.   function setXMax($value) {
  342.     $this->xMax = $value;
  343.     $this->updateAxis();
  344.   }
  345.  
  346.   /**
  347.    * Get min value for Y axis
  348.    *
  349.    * @return float $value
  350.    */
  351.   function getYMin() {
  352.     if($this->auto) {
  353.       if(is_null($this->yMin)) {
  354.         $min = array_min($this->datay);
  355.         if($min > 0) {
  356.           return 0;
  357.         }
  358.       }
  359.     }
  360.     return is_null($this->yMin) ? array_min($this->datay) : (float)$this->yMin;
  361.   }
  362.  
  363.   /**
  364.    * Get max value for Y axis
  365.    *
  366.    * @return float $value
  367.    */
  368.   function getYMax() {
  369.     if($this->auto) {
  370.       if(is_null($this->yMax)) {
  371.         $max = array_max($this->datay);
  372.         if($max < 0) {
  373.           return 0;
  374.         }
  375.       }
  376.     }
  377.     return is_null($this->yMax) ? array_max($this->datay) : (float)$this->yMax;
  378.   }
  379.  
  380.   /**
  381.    * Get min value for X axis
  382.    *
  383.    * @return float $value
  384.    */
  385.   function getXMin() {
  386.     return floor(is_null($this->xMin) ? array_min($this->datax) : $this->xMin);
  387.   }
  388.  
  389.   /**
  390.    * Get max value for X axis
  391.    *
  392.    * @return float $value
  393.    */
  394.   function getXMax() {
  395.     return (ceil(is_null($this->xMax) ? array_max($this->datax) : (float)$this->xMax)) + ($this->getXCenter() ? 1 : 0);
  396.   }
  397.  
  398.   /**
  399.    * Get min value with spaces for Y axis
  400.    *
  401.    * @return float $value
  402.    */
  403.   function getRealYMin() {
  404.     $min = $this->getYMin();
  405.     if($this->space->bottom !== NULL) {
  406.       $interval = ($this->getYMax() - $min) * $this->space->bottom / 100;
  407.       return $min - $interval;
  408.     } else {
  409.       return is_null($this->yMin) ? $min : (float)$this->yMin;
  410.     }
  411.   }
  412.  
  413.   /**
  414.    * Get max value with spaces for Y axis
  415.    *
  416.    * @return float $value
  417.    */
  418.   function getRealYMax() {
  419.     $max = $this->getYMax();
  420.     if($this->space->top !== NULL) {
  421.       $interval = ($max - $this->getYMin()) * $this->space->top / 100;
  422.       return $max + $interval;
  423.     } else {
  424.       return is_null($this->yMax) ? $max : (float)$this->yMax;
  425.     }
  426.   }
  427.  
  428.   function init($driver) {
  429.  
  430.     list($x1, $y1, $x2, $y2) = $this->getPosition();
  431.  
  432.     // Get space informations
  433.     list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
  434.  
  435.     $this->xAxis->setPadding($leftSpace, $rightSpace);
  436.  
  437.     if($this->space->bottom > 0 or $this->space->top > 0) {
  438.  
  439.       list($min, $max) = $this->yAxis->getRange();
  440.       $interval = $max - $min;
  441.           
  442.       $this->yAxis->setRange(
  443.       $min - $interval * $this->space->bottom / 100,
  444.       $max + $interval * $this->space->top / 100
  445.       );
  446.           
  447.     }
  448.  
  449.     // Auto-scaling mode
  450.     $this->yAxis->autoScale();
  451.  
  452.     // Number of labels is not specified
  453.     if($this->yAxis->getLabelNumber() === NULL) {
  454.       $number = round(($y2 - $y1) / 75) + 2;
  455.       $this->yAxis->setLabelNumber($number);
  456.     }
  457.  
  458.     $this->xAxis->line->setX($x1, $x2);
  459.     $this->yAxis->line->setY($y2, $y1);
  460.  
  461.     // Set ticks
  462.  
  463.     $this->xAxis->ticks['major']->setNumber($this->getXAxisNumber());
  464.     $this->yAxis->ticks['major']->setNumber($this->yAxis->getLabelNumber());
  465.  
  466.  
  467.     // Center X axis on zero
  468.     if($this->xAxisZero) {
  469.       $this->xAxis->setYCenter($this->yAxis, 0);
  470.     }
  471.  
  472.     // Center Y axis on zero
  473.     if($this->yAxisZero) {
  474.       $this->yAxis->setXCenter($this->xAxis, 0);
  475.     }
  476.  
  477.     // Set axis labels
  478.     $labels = array();
  479.  
  480.     list($xMin, $xMax) = $this->xAxis->getRange();
  481.     for($i = $xMin; $i <= $xMax; $i++) {
  482.       $labels[] = $i;
  483.     }
  484.     $this->xAxis->label->set($labels);
  485.  
  486.     parent::init($driver);
  487.  
  488.     list($x1, $y1, $x2, $y2) = $this->getPosition();
  489.  
  490.     list($leftSpace, $rightSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
  491.  
  492.     // Create the grid
  493.     $this->createGrid();
  494.  
  495.     // Draw the grid
  496.     $this->grid->setSpace($leftSpace, $rightSpace, 0, 0);
  497.     $this->grid->draw($driver, $x1, $y1, $x2, $y2);
  498.  
  499.   }
  500.  
  501.   function drawEnvelope($driver) {
  502.  
  503.     list($x1, $y1, $x2, $y2) = $this->getPosition();
  504.  
  505.     if($this->getXCenter()) {
  506.       $size = $this->xAxis->getDistance(0, 1);
  507.       $this->xAxis->label->move($size / 2, 0);
  508.       $this->xAxis->label->hideLast(TRUE);
  509.     }
  510.  
  511.     // Draw top axis
  512.     if($this->xAxisPosition === PLOT_TOP or $this->xAxisPosition === PLOT_BOTH) {
  513.       $top = $this->xAxis;
  514.       if($this->xAxisZero === FALSE) {
  515.         $top->line->setY($y1, $y1);
  516.       }
  517.       $top->label->setAlign(NULL, LABEL_TOP);
  518.       $top->label->move(0, -3);
  519.       $top->title->move(0, -25);
  520.       $top->draw($driver);
  521.     }
  522.  
  523.     // Draw bottom axis
  524.     if($this->xAxisPosition === PLOT_BOTTOM or $this->xAxisPosition === PLOT_BOTH) {
  525.       $bottom = $this->xAxis;
  526.       if($this->xAxisZero === FALSE) {
  527.         $bottom->line->setY($y2, $y2);
  528.       }
  529.       $bottom->label->setAlign(NULL, LABEL_BOTTOM);
  530.       $bottom->label->move(0, 3);
  531.       $bottom->reverseTickStyle();
  532.       $bottom->title->move(0, 25);
  533.       $bottom->draw($driver);
  534.     }
  535.  
  536.     // Draw left axis
  537.     if($this->yAxisPosition === PLOT_LEFT or $this->yAxisPosition === PLOT_BOTH) {
  538.       $left = $this->yAxis;
  539.       if($this->yAxisZero === FALSE) {
  540.         $left->line->setX($x1, $x1);
  541.       }
  542.       $left->label->setAlign(LABEL_RIGHT);
  543.       $left->label->move(-6, 0);
  544.       $left->title->move(-25, 0);
  545.       $left->draw($driver);
  546.     }
  547.  
  548.     // Draw right axis
  549.     if($this->yAxisPosition === PLOT_RIGHT or $this->yAxisPosition === PLOT_BOTH) {
  550.       $right = $this->yAxis;
  551.       if($this->yAxisZero === FALSE) {
  552.         $right->line->setX($x2, $x2);
  553.       }
  554.       $right->label->setAlign(LABEL_LEFT);
  555.       $right->label->move(6, 0);
  556.       $right->reverseTickStyle();
  557.       $right->title->move(25, 0);
  558.       $right->draw($driver);
  559.     }
  560.  
  561.   }
  562.  
  563.   function createGrid() {
  564.  
  565.     $max = $this->getRealYMax();
  566.     $min = $this->getRealYMin();
  567.  
  568.     $number = $this->yAxis->getLabelNumber() - 1;
  569.  
  570.     if($number < 1) {
  571.       return;
  572.     }
  573.  
  574.     // Horizontal lines of the grid
  575.  
  576.     $h = array();
  577.     for($i = 0; $i <= $number; $i++) {
  578.       $h[] = $i / $number;
  579.     }
  580.  
  581.     // Vertical lines
  582.  
  583.     $major = $this->yAxis->tick('major');
  584.     $interval = $major->getInterval();
  585.     $number = $this->getXAxisNumber() - 1;
  586.  
  587.     $w = array();
  588.  
  589.     if($number > 0) {
  590.           
  591.       for($i = 0; $i <= $number; $i++) {
  592.         if($i%$interval === 0) {
  593.           $w[] = $i / $number;
  594.         }
  595.       }
  596.           
  597.     }
  598.  
  599.     $this->grid->setGrid($w, $h);
  600.  
  601.   }
  602.  
  603.   /**
  604.    * Change values of Y axis
  605.    * This method ignores not numeric values
  606.    *
  607.    * @param array $datay 
  608.    * @param array $datax 
  609.    */
  610.   function setValues($datay, $datax = NULL) {
  611.  
  612.     $this->checkArray($datay);
  613.  
  614.     foreach($datay as $key => $value) {
  615.       unset($datay[$key]);
  616.       $datay[(int)$key] = $value;
  617.     }
  618.  
  619.     if($datax === NULL) {
  620.       $datax = array();
  621.       for($i = 0; $i < count($datay); $i++) {
  622.         $datax[] = $i;
  623.       }
  624.     } else {
  625.       foreach($datax as $key => $value) {
  626.         unset($datax[$key]);
  627.         $datax[(int)$key] = $value;
  628.       }
  629.     }
  630.  
  631.     $this->checkArray($datax);
  632.  
  633.     if(count($datay) === count($datax)) {
  634.  
  635.       // Set values
  636.       $this->datay = $datay;
  637.       $this->datax = $datax;
  638.       // Update axis with the new awvalues
  639.       $this->updateAxis();
  640.     } else {
  641.       awImage::drawError("Class Plot: Plots must have the same number of X and Y points.");
  642.     }
  643.  
  644.   }
  645.  
  646.   /**
  647.    * Return begin and end values
  648.    *
  649.    * @return array 
  650.    */
  651.   function getLimit() {
  652.  
  653.     $i = 0;
  654.     while(array_key_exists($i, $this->datay) and $this->datay[$i] === NULL) {
  655.       $i++;
  656.     }
  657.     $start = $i;
  658.     $i = count($this->datay) - 1;
  659.     while(array_key_exists($i, $this->datay) and $this->datay[$i] === NULL) {
  660.       $i--;
  661.     }
  662.     $stop = $i;
  663.  
  664.     return array($start, $stop);
  665.  
  666.   }
  667.  
  668.   /**
  669.    * Return TRUE if labels must be centered on X axis, FALSE otherwise
  670.    *
  671.    * @return bool 
  672.    */
  673.    
  674.  
  675.   function updateAxis() {
  676.  
  677.     $this->xAxis->setRange(
  678.     $this->getXMin(),
  679.     $this->getXMax()
  680.     );
  681.     $this->yAxis->setRange(
  682.     $this->getRealYMin(),
  683.     $this->getRealYMax()
  684.     );
  685.  
  686.   }
  687.  
  688.   function checkArray(&$array) {
  689.  
  690.     if(is_array($array) === FALSE) {
  691.       awImage::drawError("Class Plot: You tried to set a value that is not an array.");
  692.     }
  693.  
  694.     foreach($array as $key => $value) {
  695.       if(is_numeric($value) === FALSE and is_null($value) === FALSE) {
  696.         awImage::drawError("Class Plot: Expected numeric values for the plot.");
  697.       }
  698.     }
  699.  
  700.     if(count($array) < 1) {
  701.       awImage::drawError("Class Plot: Your plot must have at least 1 value.");
  702.     }
  703.  
  704.   }
  705.  
  706. }
  707.  
  708. registerClass('Plot', TRUE);
  709.  
  710. class awPlotAxis {
  711.  
  712.   /**
  713.    * Left axis
  714.    *
  715.    * @var Axis 
  716.    */
  717.   var $left;
  718.  
  719.   /**
  720.    * Right axis
  721.    *
  722.    * @var Axis 
  723.    */
  724.   var $right;
  725.  
  726.   /**
  727.    * Top axis
  728.    *
  729.    * @var Axis 
  730.    */
  731.   var $top;
  732.  
  733.   /**
  734.    * Bottom axis
  735.    *
  736.    * @var Axis 
  737.    */
  738.   var $bottom;
  739.  
  740.   /**
  741.    * Build the group of axis
  742.    */
  743.   function awPlotAxis() {
  744.  
  745.     $this->left = new awAxis;
  746.     $this->left->auto(TRUE);
  747.     $this->left->label->setAlign(LABEL_RIGHT);
  748.     $this->left->label->move(-6, 0);
  749.     $this->yAxis($this->left);
  750.     $this->left->setTickStyle(TICK_OUT);
  751.     $this->left->title->move(-25, 0);
  752.  
  753.     $this->right = new awAxis;
  754.     $this->right->auto(TRUE);
  755.     $this->right->label->setAlign(LABEL_LEFT);
  756.     $this->right->label->move(6, 0);
  757.     $this->yAxis($this->right);
  758.     $this->right->setTickStyle(TICK_IN);
  759.     $this->right->title->move(25, 0);
  760.  
  761.     $this->top = new awAxis;
  762.     $this->top->label->setAlign(NULL, LABEL_TOP);
  763.     $this->top->label->move(0, -3);
  764.     $this->xAxis($this->top);
  765.     $this->top->setTickStyle(TICK_OUT);
  766.     $this->top->title->move(0, -25);
  767.  
  768.     $this->bottom = new awAxis;
  769.     $this->bottom->label->setAlign(NULL, LABEL_BOTTOM);
  770.     $this->bottom->label->move(0, 3);
  771.     $this->xAxis($this->bottom);
  772.     $this->bottom->setTickStyle(TICK_IN);
  773.     $this->bottom->title->move(0, 25);
  774.  
  775.   }
  776.  
  777.   function xAxis(&$axis) {
  778.  
  779.     $axis->addTick('major', new awTick(0, 5));
  780.     $axis->addTick('minor', new awTick(0, 3));
  781.     $axis->label->setFont(new awTuffy(7));
  782.  
  783.   }
  784.  
  785.   function yAxis(&$axis) {
  786.  
  787.     $axis->addTick('major', new awTick(0, 5));
  788.     $axis->addTick('minor', new awTick(0, 3));
  789.     $axis->setNumberByTick('minor', 'major', 3);
  790.     $axis->label->setFont(new awTuffy(7));
  791.     $axis->title->setAngle(90);
  792.  
  793.   }
  794.  
  795. }
  796.  
  797. registerClass('PlotAxis');
  798.  
  799. /**
  800.  * A graph with axis can contain some groups of components
  801.  *
  802.  * @package linea21.externals
  803.  * @subpackage artichow
  804.  */
  805. class awPlotGroup extends awComponentGroup {
  806.  
  807.   /**
  808.    * Grid properties
  809.    *
  810.    * @var Grid 
  811.    */
  812.   var $grid;
  813.  
  814.   /**
  815.    * Left, right, top and bottom axis
  816.    *
  817.    * @var PlotAxis 
  818.    */
  819.   var $axis;
  820.  
  821.   /**
  822.    * Set the X axis on zero
  823.    *
  824.    * @var bool 
  825.    */
  826.   var $xAxisZero = TRUE;
  827.  
  828.   /**
  829.    * Set the Y axis on zero
  830.    *
  831.    * @var bool 
  832.    */
  833.   var $yAxisZero = FALSE;
  834.  
  835.   /**
  836.    * Real axis used for Y axis
  837.    *
  838.    * @var string 
  839.    */
  840.   var $yRealAxis = PLOT_LEFT;
  841.  
  842.   /**
  843.    * Real axis used for X axis
  844.    *
  845.    * @var string 
  846.    */
  847.   var $xRealAxis = PLOT_BOTTOM;
  848.  
  849.   /**
  850.    * Change min value for Y axis
  851.    *
  852.    * @var mixed 
  853.    */
  854.   var $yMin = NULL;
  855.  
  856.   /**
  857.    * Change max value for Y axis
  858.    *
  859.    * @var mixed 
  860.    */
  861.   var $yMax = NULL;
  862.  
  863.   /**
  864.    * Change min value for X axis
  865.    *
  866.    * @var mixed 
  867.    */
  868.   var $xMin = NULL;
  869.  
  870.   /**
  871.    * Change max value for X axis
  872.    *
  873.    * @var mixed 
  874.    */
  875.   var $xMax = NULL;
  876.  
  877.   /**
  878.    * Build the PlotGroup
  879.    *
  880.    */
  881.   function awPlotGroup() {
  882.  
  883.     parent::awComponentGroup();
  884.  
  885.     $this->grid = new awGrid;
  886.     $this->grid->setBackgroundColor(new awWhite);
  887.  
  888.     $this->axis = new awPlotAxis;
  889.  
  890.   }
  891.  
  892.   /**
  893.    * Set the X axis on zero or not
  894.    *
  895.    * @param bool $zero 
  896.    */
  897.   function setXAxisZero($zero) {
  898.     $this->xAxisZero = (bool)$zero;
  899.   }
  900.  
  901.   /**
  902.    * Set the Y axis on zero or not
  903.    *
  904.    * @param bool $zero 
  905.    */
  906.   function setYAxisZero($zero) {
  907.     $this->yAxisZero = (bool)$zero;
  908.   }
  909.  
  910.   /**
  911.    * Change min value for Y axis
  912.    * Set NULL for auto selection.
  913.    *
  914.    * @param float $value 
  915.    */
  916.   function setYMin($value) {
  917.     $this->axis->left->auto(FALSE);
  918.     $this->axis->right->auto(FALSE);
  919.     $this->yMin = $value;
  920.   }
  921.  
  922.   /**
  923.    * Change max value for Y axis
  924.    * Set NULL for auto selection.
  925.    *
  926.    * @param float $value 
  927.    */
  928.   function setYMax($value) {
  929.     $this->axis->left->auto(FALSE);
  930.     $this->axis->right->auto(FALSE);
  931.     $this->yMax = $value;
  932.   }
  933.  
  934.   /**
  935.    * Change min value for X axis
  936.    * Set NULL for auto selection.
  937.    *
  938.    * @param float $value 
  939.    */
  940.   function setXMin($value) {
  941.     $this->xMin = $value;
  942.   }
  943.  
  944.   /**
  945.    * Change max value for X axis
  946.    * Set NULL for auto selection.
  947.    *
  948.    * @param float $value 
  949.    */
  950.   function setXMax($value) {
  951.     $this->xMax = $value;
  952.   }
  953.  
  954.   /**
  955.    * Get min value for X axis
  956.    *
  957.    * @return float $value
  958.    */
  959.   function getXMin() {
  960.  
  961.     return $this->getX('min');
  962.  
  963.   }
  964.  
  965.   /**
  966.    * Get max value for X axis
  967.    *
  968.    * @return float $value
  969.    */
  970.   function getXMax() {
  971.  
  972.     return $this->getX('max');
  973.  
  974.   }
  975.  
  976.   function getX($type) {
  977.  
  978.     switch($type) {
  979.       case 'max' :
  980.         if($this->xMax !== NULL) {
  981.           return $this->xMax;
  982.         }
  983.         break;
  984.       case 'min' :
  985.         if($this->xMin !== NULL) {
  986.           return $this->xMin;
  987.         }
  988.         break;
  989.     }
  990.  
  991.     $value = NULL;
  992.     $get = 'getX'.ucfirst($type);
  993.  
  994.     for($i = 0; $i < count($this->components); $i++) {
  995.  
  996.       $component = $this->components[$i];
  997.  
  998.       if($value === NULL) {
  999.         $value = $component->$get();
  1000.       } else {
  1001.         $value = $type($value, $component->$get());
  1002.       }
  1003.           
  1004.     }
  1005.  
  1006.     return $value;
  1007.  
  1008.   }
  1009.  
  1010.   /**
  1011.    * Get min value with spaces for Y axis
  1012.    *
  1013.    * @param string $axis Axis name
  1014.    * @return float $value
  1015.    */
  1016.   function getRealYMin($axis = NULL) {
  1017.  
  1018.     if($axis === NULL) {
  1019.       return NULL;
  1020.     }
  1021.  
  1022.     $min = $this->getRealY('min', $axis);
  1023.     $max = $this->getRealY('max', $axis);
  1024.  
  1025.     if($this->space->bottom !== NULL) {
  1026.       $interval = ($min - $max) * $this->space->bottom / 100;
  1027.       return $min + $interval;
  1028.     } else {
  1029.       return $min;
  1030.     }
  1031.  
  1032.   }
  1033.  
  1034.   /**
  1035.    * Get max value with spaces for Y axis
  1036.    *
  1037.    * @param string $axis Axis name
  1038.    * @return float $value
  1039.    */
  1040.   function getRealYMax($axis = NULL) {
  1041.  
  1042.     if($axis === NULL) {
  1043.       return NULL;
  1044.     }
  1045.  
  1046.     $min = $this->getRealY('min', $axis);
  1047.     $max = $this->getRealY('max', $axis);
  1048.  
  1049.     if($this->space->top !== NULL) {
  1050.       $interval = ($max - $min) * $this->space->top / 100;
  1051.       return $max + $interval;
  1052.     } else {
  1053.       return $max;
  1054.     }
  1055.  
  1056.   }
  1057.  
  1058.   function getRealY($type, $axis) {
  1059.  
  1060.     switch($type) {
  1061.       case 'max' :
  1062.         if($this->yMax !== NULL) {
  1063.           return $this->yMax;
  1064.         }
  1065.         break;
  1066.       case 'min' :
  1067.         if($this->yMin !== NULL) {
  1068.           return $this->yMin;
  1069.         }
  1070.         break;
  1071.     }
  1072.  
  1073.     $value = NULL;
  1074.     $get = 'getY'.ucfirst($type);
  1075.  
  1076.     for($i = 0; $i < count($this->components); $i++) {
  1077.  
  1078.       $component = $this->components[$i];
  1079.           
  1080.       switch($axis) {
  1081.             
  1082.         case PLOT_LEFT :
  1083.         case PLOT_RIGHT :
  1084.           $test = ($component->getYAxis() === $axis);
  1085.           break;
  1086.         default :
  1087.           $test = FALSE;
  1088.               
  1089.       }
  1090.           
  1091.       if($test) {
  1092.  
  1093.         $auto = $component->yAxis->isAuto();
  1094.         $this->axis->{$axis}->auto($auto);
  1095.  
  1096.         if($value === NULL) {
  1097.           $value = $component->$get();
  1098.         } else {
  1099.           $value = $type($value, $component->$get());
  1100.         }
  1101.  
  1102.       }
  1103.           
  1104.     }
  1105.  
  1106.     return $value;
  1107.  
  1108.   }
  1109.  
  1110.   function init($driver) {
  1111.  
  1112.     list($x1, $y1, $x2, $y2) = $this->getPosition();
  1113.  
  1114.     // Get PlotGroup space
  1115.     list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
  1116.  
  1117.     // Count values in the group
  1118.     $values = $this->getXAxisNumber();
  1119.  
  1120.     // Init the PlotGroup
  1121.     $this->axis->top->line->setX($x1, $x2);
  1122.     $this->axis->bottom->line->setX($x1, $x2);
  1123.     $this->axis->left->line->setY($y2, $y1);
  1124.     $this->axis->right->line->setY($y2, $y1);
  1125.  
  1126.     $this->axis->top->setPadding($leftSpace, $rightSpace);
  1127.     $this->axis->bottom->setPadding($leftSpace, $rightSpace);
  1128.  
  1129.     $xMin = $this->getXMin();
  1130.     $xMax = $this->getXMax();
  1131.  
  1132.     $this->axis->top->setRange($xMin, $xMax);
  1133.     $this->axis->bottom->setRange($xMin, $xMax);
  1134.  
  1135.     for($i = 0; $i < count($this->components); $i++) {
  1136.  
  1137.           
  1138.       $component = &$this->components[$i];
  1139.           
  1140.       $component->auto($this->auto);
  1141.           
  1142.       // Copy space to the component
  1143.           
  1144.       $component->setSpace($this->space->left, $this->space->right, $this->space->top, $this->space->bottom);
  1145.           
  1146.       $component->xAxis->setPadding($leftSpace, $rightSpace);
  1147.       $component->xAxis->line->setX($x1, $x2);
  1148.           
  1149.       $component->yAxis->line->setY($y2, $y1);
  1150.           
  1151.     }
  1152.  
  1153.     // Set Y axis range
  1154.     foreach(array('left', 'right') as $axis) {
  1155.  
  1156.       if($this->isAxisUsed($axis)) {
  1157.             
  1158.         $min = $this->getRealYMin($axis);
  1159.         $max = $this->getRealYMax($axis);
  1160.  
  1161.         $interval = $max - $min;
  1162.  
  1163.         $this->axis->{$axis}->setRange(
  1164.         $min - $interval * $this->space->bottom / 100,
  1165.         $max + $interval * $this->space->top / 100
  1166.         );
  1167.  
  1168.         // Auto-scaling mode
  1169.         if($this->axis->{$axis}->isAuto()) {
  1170.           $this->axis->{$axis}->autoScale();
  1171.         }
  1172.  
  1173.       }
  1174.           
  1175.     }
  1176.  
  1177.     if($this->axis->left->getLabelNumber() === NULL) {
  1178.       $number = round(($y2 - $y1) / 75) + 2;
  1179.       $this->axis->left->setLabelNumber($number);
  1180.     }
  1181.  
  1182.     if($this->axis->right->getLabelNumber() === NULL) {
  1183.       $number = round(($y2 - $y1) / 75) + 2;
  1184.       $this->axis->right->setLabelNumber($number);
  1185.     }
  1186.  
  1187.     // Center labels on X axis if needed
  1188.     $test = array(PLOT_TOP => FALSE, PLOT_BOTTOM => FALSE);
  1189.  
  1190.     for($i = 0; $i < count($this->components); $i++) {
  1191.  
  1192.           
  1193.       $component = &$this->components[$i];
  1194.           
  1195.           
  1196.       if($component->getValues() !== NULL) {
  1197.  
  1198.         $axis = $component->getXAxis();
  1199.  
  1200.         if($test[$axis] === FALSE) {
  1201.  
  1202.           // Center labels for bar plots
  1203.           if($component->getXCenter()) {
  1204.             $size = $this->axis->{$axis}->getDistance(0, 1);
  1205.             $this->axis->{$axis}->label->move($size / 2, 0);
  1206.             $this->axis->{$axis}->label->hideLast(TRUE);
  1207.             $test[$axis] = TRUE;
  1208.           }
  1209.               
  1210.         }
  1211.  
  1212.       }
  1213.           
  1214.           
  1215.     }
  1216.  
  1217.     // Set axis labels
  1218.     $labels = array();
  1219.     for($i = $xMin; $i <= $xMax; $i++) {
  1220.       $labels[] = $i;
  1221.     }
  1222.     if($this->axis->top->label->count() === 0) {
  1223.       $this->axis->top->label->set($labels);
  1224.     }
  1225.     if($this->axis->bottom->label->count() === 0) {
  1226.       $this->axis->bottom->label->set($labels);
  1227.     }
  1228.  
  1229.     // Set ticks
  1230.  
  1231.     $this->axis->top->ticks['major']->setNumber($values);
  1232.     $this->axis->bottom->ticks['major']->setNumber($values);
  1233.     $this->axis->left->ticks['major']->setNumber($this->axis->left->getLabelNumber());
  1234.     $this->axis->right->ticks['major']->setNumber($this->axis->right->getLabelNumber());
  1235.  
  1236.  
  1237.     // Set X axis on zero
  1238.     if($this->xAxisZero) {
  1239.       $axis = $this->selectYAxis();
  1240.       $this->axis->bottom->setYCenter($axis, 0);
  1241.       $this->axis->top->setYCenter($axis, 0);
  1242.     }
  1243.  
  1244.     // Set Y axis on zero
  1245.     if($this->yAxisZero) {
  1246.       $axis = $this->selectXAxis();
  1247.       $this->axis->left->setXCenter($axis, 1);
  1248.       $this->axis->right->setXCenter($axis, 1);
  1249.     }
  1250.  
  1251.     parent::init($driver);
  1252.  
  1253.     list($leftSpace, $rightSpace, $topSpace, $bottomSpace) = $this->getSpace($x2 - $x1, $y2 - $y1);
  1254.  
  1255.     // Create the grid
  1256.     $this->createGrid();
  1257.  
  1258.     // Draw the grid
  1259.     $this->grid->setSpace($leftSpace, $rightSpace, 0, 0);
  1260.     $this->grid->draw($driver, $x1, $y1, $x2, $y2);
  1261.  
  1262.   }
  1263.  
  1264.   function drawComponent($driver, $x1, $y1, $x2, $y2, $aliasing) {
  1265.  
  1266.     $xMin = $this->getXMin();
  1267.     $xMax = $this->getXMax();
  1268.  
  1269.     $maxLeft = $this->getRealYMax(PLOT_LEFT);
  1270.     $maxRight = $this->getRealYMax(PLOT_RIGHT);
  1271.  
  1272.     $minLeft = $this->getRealYMin(PLOT_LEFT);
  1273.     $minRight = $this->getRealYMin(PLOT_RIGHT);
  1274.  
  1275.     foreach($this->components as $component) {
  1276.  
  1277.       $min = $component->getYMin();
  1278.       $max = $component->getYMax();
  1279.           
  1280.       // Set component minimum and maximum
  1281.       if($component->getYAxis() === PLOT_LEFT) {
  1282.             
  1283.         list($min, $max) = $this->axis->left->getRange();
  1284.             
  1285.         $component->setYMin($min);
  1286.         $component->setYMax($max);
  1287.  
  1288.       } else {
  1289.             
  1290.         list($min, $max) = $this->axis->right->getRange();
  1291.  
  1292.         $component->setYMin($min);
  1293.         $component->setYMax($max);
  1294.  
  1295.       }
  1296.           
  1297.       $component->setXAxisZero($this->xAxisZero);
  1298.       $component->setYAxisZero($this->yAxisZero);
  1299.           
  1300.       $component->xAxis->setRange($xMin, $xMax);
  1301.  
  1302.       $component->drawComponent(
  1303.       $driver,
  1304.       $x1, $y1,
  1305.       $x2, $y2,
  1306.       $aliasing
  1307.       );
  1308.           
  1309.       $component->setYMin($min);
  1310.       $component->setYMax($max);
  1311.           
  1312.     }
  1313.  
  1314.   }
  1315.  
  1316.   function drawEnvelope($driver) {
  1317.  
  1318.     list($x1, $y1, $x2, $y2) = $this->getPosition();
  1319.  
  1320.     // Hide unused axis
  1321.     foreach(array(PLOT_LEFT, PLOT_RIGHT, PLOT_TOP, PLOT_BOTTOM) as $axis) {
  1322.       if($this->isAxisUsed($axis) === FALSE) {
  1323.         $this->axis->{$axis}->hide(TRUE);
  1324.       }
  1325.     }
  1326.  
  1327.     // Draw top axis
  1328.     $top = $this->axis->top;
  1329.     if($this->xAxisZero === FALSE) {
  1330.       $top->line->setY($y1, $y1);
  1331.     }
  1332.     $top->draw($driver);
  1333.  
  1334.     // Draw bottom axis
  1335.     $bottom = $this->axis->bottom;
  1336.     if($this->xAxisZero === FALSE) {
  1337.       $bottom->line->setY($y2, $y2);
  1338.     }
  1339.     $bottom->draw($driver);
  1340.  
  1341.     // Draw left axis
  1342.     $left = $this->axis->left;
  1343.     if($this->yAxisZero === FALSE) {
  1344.       $left->line->setX($x1, $x1);
  1345.     }
  1346.     $left->draw($driver);
  1347.  
  1348.     // Draw right axis
  1349.     $right = $this->axis->right;
  1350.     if($this->yAxisZero === FALSE) {
  1351.       $right->line->setX($x2, $x2);
  1352.     }
  1353.     $right->draw($driver);
  1354.  
  1355.   }
  1356.  
  1357.   /**
  1358.    * Is the specified axis used ?
  1359.    *
  1360.    * @param string $axis Axis name
  1361.    * @return bool 
  1362.    */
  1363.   function isAxisUsed($axis) {
  1364.  
  1365.     for($i = 0; $i < count($this->components); $i++) {
  1366.  
  1367.       $component = $this->components[$i];
  1368.           
  1369.       switch($axis) {
  1370.             
  1371.         case PLOT_LEFT :
  1372.         case PLOT_RIGHT :
  1373.           if($component->getYAxis() === $axis) {
  1374.             return TRUE;
  1375.           }
  1376.           break;
  1377.               
  1378.         case PLOT_TOP :
  1379.         case PLOT_BOTTOM :
  1380.           if($component->getXAxis() === $axis) {
  1381.             return TRUE;
  1382.           }
  1383.           break;
  1384.               
  1385.       }
  1386.           
  1387.     }
  1388.  
  1389.     return FALSE;
  1390.  
  1391.   }
  1392.  
  1393.   function createGrid() {
  1394.  
  1395.     $max = $this->getRealYMax(PLOT_LEFT);
  1396.     $min = $this->getRealYMin(PLOT_RIGHT);
  1397.  
  1398.     // Select axis (left if possible, right otherwise)
  1399.     $axis = $this->selectYAxis();
  1400.  
  1401.     $number = $axis->getLabelNumber() - 1;
  1402.  
  1403.     if($number < 1) {
  1404.       return;
  1405.     }
  1406.  
  1407.     // Horizontal lines of grid
  1408.  
  1409.     $h = array();
  1410.     for($i = 0; $i <= $number; $i++) {
  1411.       $h[] = $i / $number;
  1412.     }
  1413.  
  1414.     // Vertical lines
  1415.  
  1416.     $major = $axis->tick('major');
  1417.     $interval = $major->getInterval();
  1418.     $number = $this->getXAxisNumber() - 1;
  1419.  
  1420.     $w = array();
  1421.  
  1422.     if($number > 0) {
  1423.           
  1424.       for($i = 0; $i <= $number; $i++) {
  1425.         if($i%$interval === 0) {
  1426.           $w[] = $i / $number;
  1427.         }
  1428.       }
  1429.           
  1430.     }
  1431.  
  1432.     $this->grid->setGrid($w, $h);
  1433.  
  1434.   }
  1435.  
  1436.   function selectYAxis(){
  1437.  
  1438.     // Select axis (left if possible, right otherwise)
  1439.     if($this->isAxisUsed(PLOT_LEFT)) {
  1440.       $axis = $this->axis->left;
  1441.     } else {
  1442.       $axis = $this->axis->right;
  1443.     }
  1444.  
  1445.     return $axis;
  1446.  
  1447.   }
  1448.  
  1449.   function selectXAxis(){
  1450.  
  1451.     // Select axis (bottom if possible, top otherwise)
  1452.     if($this->isAxisUsed(PLOT_BOTTOM)) {
  1453.       $axis = $this->axis->bottom;
  1454.     } else {
  1455.       $axis = $this->axis->top;
  1456.     }
  1457.  
  1458.     return $axis;
  1459.  
  1460.   }
  1461.  
  1462.   function getXAxisNumber() {
  1463.     $offset = $this->components[0];
  1464.     $max = $offset->getXAxisNumber();
  1465.     for($i = 1; $i < count($this->components); $i++) {
  1466.       $offset = $this->components[$i];
  1467.       $max = max($max, $offset->getXAxisNumber());
  1468.     }
  1469.     return $max;
  1470.   }
  1471.  
  1472. }
  1473.  
  1474. registerClass('PlotGroup');
  1475. ?>

Documentation generated on Fri, 01 Apr 2011 09:34:09 +0200 by phpDocumentor 1.4.1