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

Source for file Axis.class.php

Documentation is available at Axis.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__)."/../Graph.class.php";
  11.  
  12. /**
  13.  * Handle axis
  14.  *
  15.  * @package linea21.externals
  16.  * @subpackage artichow
  17.  */
  18. class awAxis {
  19.  
  20.     /**
  21.      * Axis line
  22.      *
  23.      * @var Line 
  24.      */
  25.     public $line;
  26.  
  27.     /**
  28.      * Axis labels
  29.      *
  30.      * @var Label 
  31.      */
  32.     public $label;
  33.  
  34.     /**
  35.      * Axis title
  36.      *
  37.      * @var Label 
  38.      */
  39.     public $title;
  40.  
  41.     /**
  42.      * Title position
  43.      *
  44.      * @var float 
  45.      */
  46.     protected $titlePosition = 0.5;
  47.  
  48.     /**
  49.      * Labels number
  50.      *
  51.      * @var int 
  52.      */
  53.     protected $labelNumber;
  54.  
  55.     /**
  56.      * Axis ticks
  57.      *
  58.      * @var array 
  59.      */
  60.     protected $ticks = array();
  61.  
  62.     /**
  63.      * Axis and ticks color
  64.      *
  65.      * @var Color 
  66.      */
  67.     protected $color;
  68.  
  69.     /**
  70.      * Axis left and right padding
  71.      *
  72.      * @var Side 
  73.      */
  74.     protected $padding;
  75.  
  76.     /**
  77.      * Axis range
  78.      *
  79.      * @var array 
  80.      */
  81.     protected $range;
  82.  
  83.     /**
  84.      * Hide axis
  85.      *
  86.      * @var bool 
  87.      */
  88.     protected $hide = FALSE;
  89.  
  90.     /**
  91.      * Auto-scaling mode
  92.      *
  93.      * @var bool 
  94.      */
  95.     protected $auto = TRUE;
  96.  
  97.     /**
  98.      * Axis range callback function
  99.      *
  100.      * @var array 
  101.      */
  102.     protected $rangeCallback = array(
  103.         'toValue' => 'toProportionalValue',
  104.         'toPosition' => 'toProportionalPosition'
  105.     );
  106.  
  107.     /**
  108.      * Build the axis
  109.      *
  110.      * @param float $min Begin of the range of the axis
  111.      * @param float $max End of the range of the axis
  112.      */
  113.     public function __construct($min NULL$max NULL{
  114.  
  115.         $this->line = new awVector(
  116.             new awPoint(00),
  117.             new awPoint(00)
  118.         );
  119.  
  120.         $this->label = new awLabel;
  121.         $this->padding = new awSide;
  122.  
  123.         $this->title = new awLabel(
  124.             NULL,
  125.             NULL,
  126.             NULL,
  127.             0
  128.         );
  129.  
  130.         $this->setColor(new awBlack);
  131.  
  132.         if($min !== NULL and $max !== NULL{
  133.             $this->setRange($min$max);
  134.         }
  135.  
  136.     }
  137.  
  138.     /**
  139.      * Enable/disable auto-scaling mode
  140.      *
  141.      * @param bool $auto 
  142.      */
  143.     public function auto($auto{
  144.         $this->auto = (bool)$auto;
  145.     }
  146.  
  147.     /**
  148.      * Get auto-scaling mode status
  149.      *
  150.      * @return bool 
  151.      */
  152.     public function isAuto({
  153.         return $this->auto;
  154.     }
  155.  
  156.     /**
  157.      * Hide axis
  158.      *
  159.      * @param bool $hide 
  160.      */
  161.     public function hide($hide TRUE{
  162.         $this->hide = (bool)$hide;
  163.     }
  164.  
  165.     /**
  166.      * Show axis
  167.      *
  168.      * @param bool $show 
  169.      */
  170.     public function show($show TRUE{
  171.         $this->hide = !(bool)$show;
  172.     }
  173.  
  174.     /**
  175.      * Return a tick object from its name
  176.      *
  177.      * @param string $name Tick object name
  178.      * @return Tick 
  179.      */
  180.     public function tick($name{
  181.         /* <php5> */
  182.         return array_key_exists($name$this->ticks$this->ticks[$nameNULL;
  183.         /* </php5> */
  184.         /* <php4> --
  185.         if(array_key_exists($name, $this->ticks)) {
  186.             return $tick = &$this->ticks[$name];
  187.         } else {
  188.             return NULL;
  189.         }
  190.         -- </php4> */
  191.     }
  192.  
  193.     /**
  194.      * Add a tick object
  195.      *
  196.      * @param string $name Tick object name
  197.      * @param awTick $tick Tick object
  198.      */
  199.     public function addTick($nameawTick $tick{
  200.         /* <php5> */
  201.         $this->ticks[$name$tick;
  202.         /* </php5> */
  203.         /* <php4> --
  204.         $this->ticks[$name] = &$tick;
  205.         -- </php4> */
  206.     }
  207.  
  208.     /**
  209.      * Delete a tick object
  210.      *
  211.      * @param string $name Tick object name
  212.      */
  213.     public function deleteTick($name{
  214.         if(array_key_exists($name$this->ticks)) {
  215.             unset($this->ticks[$name]);
  216.         }
  217.     }
  218.  
  219.     /**
  220.      * Hide all ticks
  221.      *
  222.      * @param bool $hide Hide or not ?
  223.      */
  224.     public function hideTicks($hide TRUE{
  225.         /* <php5> */
  226.         foreach($this->ticks as $tick{
  227.             $tick->hide($hide);
  228.         }
  229.         /* </php5> */
  230.         /* <php4> --
  231.         foreach($this->ticks as $key => $tick) {
  232.             $this->ticks[$key]->hide($hide);
  233.         }
  234.         -- </php4> */
  235.     }
  236.  
  237.     /**
  238.      * Change ticks style
  239.      *
  240.      * @param int $style Ticks style
  241.      */
  242.     public function setTickStyle($style{
  243.         /* <php5> */
  244.         foreach($this->ticks as $tick{
  245.             $tick->setStyle($style);
  246.         }
  247.         /* </php5> */
  248.         /* <php4> --
  249.         foreach($this->ticks as $key => $tick) {
  250.             $this->ticks[$key]->setStyle($style);
  251.         }
  252.         -- </php4> */
  253.     }
  254.  
  255.     /**
  256.      * Change ticks interval
  257.      *
  258.      * @param int $interval Ticks interval
  259.      */
  260.     public function setTickInterval($interval{
  261.         /* <php5> */
  262.         foreach($this->ticks as $tick{
  263.             $tick->setInterval($interval);
  264.         }
  265.         /* </php5> */
  266.         /* <php4> --
  267.         foreach($this->ticks as $key => $tick) {
  268.             $this->ticks[$key]->setInterval($interval);
  269.         }
  270.         -- </php4> */
  271.     }
  272.  
  273.     /**
  274.      * Change number of ticks relative to others ticks
  275.      *
  276.      * @param awTick $to Change number of theses ticks
  277.      * @param awTick $from Ticks reference
  278.      * @param float $number Number of ticks by the reference
  279.      */
  280.     public function setNumberByTick($to$from$number{
  281.         $this->ticks[$to]->setNumberByTick($this->ticks[$from]$number);
  282.     }
  283.  
  284.     /**
  285.      * Reverse ticks style
  286.      */
  287.     public function reverseTickStyle({
  288.         /* <php5> */
  289.         foreach($this->ticks as $tick{
  290.             if($tick->getStyle(=== awTick::IN{
  291.                 $tick->setStyle(awTick::OUT);
  292.             else if($tick->getStyle(=== awTick::OUT{
  293.                 $tick->setStyle(awTick::IN);
  294.             }
  295.         }
  296.         /* </php5> */
  297.         /* <php4> --
  298.         foreach($this->ticks as $key => $tick) {
  299.             if($this->ticks[$key]->getStyle() === awTick::IN) {
  300.                 $this->ticks[$key]->setStyle(awTick::OUT);
  301.             } else if($this->ticks[$key]->getStyle() === awTick::OUT) {
  302.                 $this->ticks[$key]->setStyle(awTick::IN);
  303.             }
  304.         }
  305.         -- </php4> */
  306.     }
  307.  
  308.     /**
  309.      * Change interval of labels
  310.      *
  311.      * @param int $interval Interval
  312.      */
  313.     public function setLabelInterval($interval{
  314.         $this->auto(FALSE);
  315.         $this->setTickInterval($interval);
  316.         $this->label->setInterval($interval);
  317.     }
  318.  
  319.     /**
  320.      * Change number of labels
  321.      *
  322.      * @param int $number Number of labels to display (can be NULL)
  323.      */
  324.     public function setLabelNumber($number{
  325.         $this->auto(FALSE);
  326.         $this->labelNumber = is_null($numberNULL : (int)$number;
  327.     }
  328.  
  329.     /**
  330.      * Get number of labels
  331.      *
  332.      * @return int 
  333.      */
  334.     public function getLabelNumber({
  335.         return $this->labelNumber;
  336.     }
  337.  
  338.     /**
  339.      * Change precision of labels
  340.      *
  341.      * @param int $precision Precision
  342.      */
  343.     public function setLabelPrecision($precision{
  344.         $this->auto(FALSE);
  345.         $function 'axis'.time().'_'.(microtime(1000000);
  346.         eval('function '.$function.'($value) {
  347.             return sprintf("%.'.(int)$precision.'f", $value);
  348.         }');
  349.         $this->label->setCallbackFunction($function);
  350.     }
  351.  
  352.     /**
  353.      * Change text of labels
  354.      *
  355.      * @param array $texts Some texts
  356.      */
  357.     public function setLabelText($texts{
  358.         if(is_array($texts)) {
  359.             $this->auto(FALSE);
  360.             $function 'axis'.time().'_'.(microtime(1000000);
  361.             eval('function '.$function.'($value) {
  362.                 $texts = '.var_export($textsTRUE).';
  363.                 return isset($texts[$value]) ? $texts[$value] : \'?\';
  364.             }');
  365.             $this->label->setCallbackFunction($function);
  366.         }
  367.     }
  368.  
  369.     /**
  370.      * Get the position of a point
  371.      *
  372.      * @param awAxis $xAxis X axis
  373.      * @param awAxis $yAxis Y axis
  374.      * @param awPoint $p Position of the point
  375.      * @return Point Position on the axis
  376.      */
  377.     public static function toPosition(awAxis $xAxisawAxis $yAxisawPoint $p{
  378.  
  379.         $p1 $xAxis->getPointFromValue($p->x);
  380.         $p2 $yAxis->getPointFromValue($p->y);
  381.  
  382.         return new awPoint(
  383.             round($p1->x),
  384.             round($p2->y)
  385.         );
  386.  
  387.     }
  388.  
  389.     /**
  390.      * Change title alignment
  391.      *
  392.      * @param int $alignment New Alignment
  393.      */
  394.     public function setTitleAlignment($alignment{
  395.  
  396.         switch($alignment{
  397.  
  398.             case awLabel::TOP :
  399.                 $this->setTitlePosition(1);
  400.                 $this->title->setAlign(NULLawLabel::BOTTOM);
  401.                 break;
  402.  
  403.             case awLabel::BOTTOM :
  404.                 $this->setTitlePosition(0);
  405.                 $this->title->setAlign(NULLawLabel::TOP);
  406.                 break;
  407.  
  408.             case awLabel::LEFT :
  409.                 $this->setTitlePosition(0);
  410.                 $this->title->setAlign(awLabel::LEFT);
  411.                 break;
  412.  
  413.             case awLabel::RIGHT :
  414.                 $this->setTitlePosition(1);
  415.                 $this->title->setAlign(awLabel::RIGHT);
  416.                 break;
  417.  
  418.         }
  419.  
  420.     }
  421.  
  422.     /**
  423.      * Change title position on the axis
  424.      *
  425.      * @param float $position A new awposition between 0 and 1
  426.      */
  427.     public function setTitlePosition($position{
  428.         $this->titlePosition = (float)$position;
  429.     }
  430.  
  431.     /**
  432.      * Change axis and axis title color
  433.      *
  434.      * @param awColor $color 
  435.      */
  436.     public function setColor(awColor $color{
  437.         $this->color = $color;
  438.         $this->title->setColor($color);
  439.     }
  440.  
  441.     /**
  442.      * Change axis padding
  443.      *
  444.      * @param int $left Left padding in pixels
  445.      * @param int $right Right padding in pixels
  446.      */
  447.     public function setPadding($left$right{
  448.         $this->padding->set($left$right);
  449.     }
  450.  
  451.     /**
  452.      * Get axis padding
  453.      *
  454.      * @return Side 
  455.      */
  456.     public function getPadding({
  457.         return $this->padding;
  458.     }
  459.  
  460.     /**
  461.      * Change axis range
  462.      *
  463.      * @param float $min 
  464.      * @param float $max 
  465.      */
  466.     public function setRange($min$max{
  467.         if($min !== NULL{
  468.             $this->range[0= (float)$min;
  469.         }
  470.         if($max !== NULL{
  471.             $this->range[1= (float)$max;
  472.         }
  473.     }
  474.  
  475.     /**
  476.      * Get axis range
  477.      *
  478.      * @return array 
  479.      */
  480.     public function getRange({
  481.         return $this->range;
  482.     }
  483.  
  484.     /**
  485.      * Change axis range callback function
  486.      *
  487.      * @param string $toValue Transform a position between 0 and 1 to a value
  488.      * @param string $toPosition Transform a value to a position between 0 and 1 on the axis
  489.      */
  490.     public function setRangeCallback($toValue$toPosition{
  491.         $this->rangeCallback = array(
  492.             'toValue' => (string)$toValue,
  493.             'toPosition' => (string)$toPosition
  494.         );
  495.     }
  496.  
  497.     /**
  498.      * Center X values of the axis
  499.      *
  500.      * @param awAxis $axis An axis
  501.      * @param float $value The reference value on the axis
  502.      */
  503.     public function setXCenter(awAxis $axis$value{
  504.  
  505.         // Check vector angle
  506.         if($this->line->isVertical(=== FALSE{
  507.             awImage::drawError("Class Axis: setXCenter() can only be used on vertical axes.");
  508.         }
  509.  
  510.         $p $axis->getPointFromValue($value);
  511.  
  512.         $this->line->setX(
  513.             $p->x,
  514.             $p->x
  515.         );
  516.  
  517.     }
  518.  
  519.     /**
  520.      * Center Y values of the axis
  521.      *
  522.      * @param awAxis $axis An axis
  523.      * @param float $value The reference value on the axis
  524.      */
  525.     public function setYCenter(awAxis $axis$value{
  526.  
  527.         // Check vector angle
  528.         if($this->line->isHorizontal(=== FALSE{
  529.             awImage::drawError("Class Axis: setYCenter() can only be used on horizontal axes.");
  530.         }
  531.  
  532.         $p $axis->getPointFromValue($value);
  533.  
  534.         $this->line->setY(
  535.             $p->y,
  536.             $p->y
  537.         );
  538.  
  539.     }
  540.  
  541.     /**
  542.      * Get the distance between to values on the axis
  543.      *
  544.      * @param float $from The first value
  545.      * @param float $to The last value
  546.      * @return Point 
  547.      */
  548.     public function getDistance($from$to{
  549.  
  550.         $p1 $this->getPointFromValue($from);
  551.         $p2 $this->getPointFromValue($to);
  552.  
  553.         return $p1->getDistance($p2);
  554.  
  555.     }
  556.  
  557.     /**
  558.      * Get a point on the axis from a value
  559.      *
  560.      * @param float $value 
  561.      * @return Point 
  562.      */
  563.     protected function getPointFromValue($value{
  564.  
  565.         $callback $this->rangeCallback['toPosition'];
  566.  
  567.         list($min$max$this->range;
  568.         $position $callback($value$min$max);
  569.  
  570.         return $this->getPointFromPosition($position);
  571.  
  572.     }
  573.  
  574.     /**
  575.      * Get a point on the axis from a position
  576.      *
  577.      * @param float $position A position between 0 and 1
  578.      * @return Point 
  579.      */
  580.     protected function getPointFromPosition($position{
  581.  
  582.         $vector $this->getVector();
  583.  
  584.         $angle $vector->getAngle();
  585.         $size $vector->getSize();
  586.  
  587.         return $vector->p1->move(
  588.             cos($angle$size $position,
  589.             -sin($angle$size $position
  590.         );
  591.  
  592.     }
  593.  
  594.     /**
  595.      * Draw axis
  596.      *
  597.      * @param awDriver $driver A driver
  598.      */
  599.     public function draw(awDriver $driver{
  600.  
  601.         if($this->hide{
  602.             return;
  603.         }
  604.  
  605.         $vector $this->getVector();
  606.  
  607.         // Draw axis ticks
  608.         $this->drawTicks($driver$vector);
  609.  
  610.         // Draw axis line
  611.         $this->line($driver);
  612.  
  613.         // Draw labels
  614.         $this->drawLabels($driver);
  615.  
  616.         // Draw axis title
  617.         $p $this->getPointFromPosition($this->titlePosition);
  618.         $this->title->draw($driver$p);
  619.  
  620.     }
  621.  
  622.     public function autoScale({
  623.  
  624.         if($this->isAuto(=== FALSE{
  625.             return;
  626.         }
  627.  
  628.         list($min$max$this->getRange();
  629.         $interval $max $min;
  630.  
  631.         if($interval 0{
  632.             $partMax $max $interval;
  633.             $partMin $min $interval;
  634.         else {
  635.             $partMax 0;
  636.             $partMin 0;
  637.         }
  638.  
  639.         $difference log($intervallog(10);
  640.         $difference floor($difference);
  641.  
  642.         $pow pow(10$difference);
  643.  
  644.         if($pow 0{
  645.             $intervalNormalize $interval $pow;
  646.         else {
  647.             $intervalNormalize 0;
  648.         }
  649.  
  650.         if($difference <= 0{
  651.  
  652.             $precision $difference * -1;
  653.  
  654.             if($intervalNormalize 2{
  655.                 $precision--;
  656.             }
  657.  
  658.         else {
  659.             $precision 0;
  660.         }
  661.  
  662.         if($min != and $max != 0{
  663.             $precision++;
  664.         }
  665.  
  666.         if($this->label->getCallbackFunction(=== NULL{
  667.             $this->setLabelPrecision($precision);
  668.         }
  669.  
  670.         if($intervalNormalize <= 1.5{
  671.             $intervalReal 1.5;
  672.             $labelNumber 4;
  673.         else if($intervalNormalize <= 2{
  674.             $intervalReal 2;
  675.             $labelNumber 5;
  676.         else if($intervalNormalize <= 3{
  677.             $intervalReal 3;
  678.             $labelNumber 4;
  679.         else if($intervalNormalize <= 4{
  680.             $intervalReal 4;
  681.             $labelNumber 5;
  682.         else if($intervalNormalize <= 5{
  683.             $intervalReal 5;
  684.             $labelNumber 6;
  685.         else if($intervalNormalize <= 8{
  686.             $intervalReal 8;
  687.             $labelNumber 5;
  688.         else if($intervalNormalize <= 10{
  689.             $intervalReal 10;
  690.             $labelNumber 6;
  691.         }
  692.  
  693.         if($min == 0{
  694.  
  695.             $this->setRange(
  696.                 $min,
  697.                 $intervalReal $pow
  698.             );
  699.  
  700.         else if($max == 0{
  701.  
  702.             $this->setRange(
  703.                 $intervalReal $pow * -1,
  704.                 0
  705.             );
  706.  
  707.         }
  708.  
  709.         $this->setLabelNumber($labelNumber);
  710.  
  711.     }
  712.  
  713.     protected function line(awDriver $driver{
  714.  
  715.         $driver->line(
  716.             $this->color,
  717.             $this->line
  718.         );
  719.  
  720.     }
  721.  
  722.     protected function drawTicks(awDriver $driverawVector $vector{
  723.  
  724.         foreach($this->ticks as $tick{
  725.             $tick->setColor($this->color);
  726.             $tick->draw($driver$vector);
  727.         }
  728.  
  729.     }
  730.  
  731.     protected function drawLabels($driver{
  732.  
  733.         if($this->labelNumber !== NULL{
  734.             list($min$max$this->range;
  735.             $number $this->labelNumber - 1;
  736.             if($number 1{
  737.                 return;
  738.             }
  739.             $function $this->rangeCallback['toValue'];
  740.             $labels array();
  741.             for($i 0$i <= $number$i++{
  742.                 $labels[$function($i $number$min$max);
  743.             }
  744.             $this->label->set($labels);
  745.         }
  746.  
  747.         $labels $this->label->count();
  748.  
  749.         for($i 0$i $labels$i++{
  750.  
  751.             $p $this->getPointFromValue($this->label->get($i));
  752.             $this->label->draw($driver$p$i);
  753.  
  754.         }
  755.  
  756.     }
  757.  
  758.     protected function getVector({
  759.  
  760.         $angle $this->line->getAngle();
  761.  
  762.         // Compute paddings
  763.         $vector new awVector(
  764.             $this->line->p1->move(
  765.                 cos($angle$this->padding->left,
  766.                 -sin($angle$this->padding->left
  767.             ),
  768.             $this->line->p2->move(
  769.                 -cos($angle$this->padding->right,
  770.                 -* -sin($angle$this->padding->right
  771.             )
  772.         );
  773.  
  774.         return $vector;
  775.  
  776.     }
  777.  
  778.     public function __clone({
  779.  
  780.         $this->label = clone $this->label;
  781.         $this->line = clone $this->line;
  782.         $this->title = clone $this->title;
  783.  
  784.         foreach($this->ticks as $name => $tick{
  785.             $this->ticks[$nameclone $tick;
  786.         }
  787.  
  788.     }
  789.  
  790. }
  791.  
  792. registerClass('Axis');
  793.  
  794. function toProportionalValue($position$min$max{
  795.     return $min ($max $min$position;
  796. }
  797.  
  798. function toProportionalPosition($value$min$max{
  799.     if($max $min == 0{
  800.         return 0;
  801.     }
  802.     return ($value $min($max $min);
  803. }
  804. ?>

Documentation generated on Fri, 16 Oct 2009 09:28:28 +0200 by phpDocumentor 1.4.1