TeeChartPHP
[ class tree: TeeChartPHP ] [ index: TeeChartPHP ] [ all elements ]

Source for file Functions.php

Documentation is available at Functions.php

  1. <?php
  2.  
  3. /**
  4.  * Functions class
  5.  *
  6.  * Description: Basic abstract function class.
  7.  * Examples of derived functions are: Add, Subtract, High, Low, Average and
  8.  * Count.
  9.  *
  10.  * @author
  11.  * @copyright (c) 1995-2010 by Steema Software SL. All Rights Reserved. <info@steema.com>
  12.  * @version 1.0
  13.  * @package TeeChartPHP
  14.  * @subpackage functions
  15.  * @link http://www.steema.com
  16.  */
  17.  
  18.  class Functions extends TeeBase {
  19.  
  20.     private $periodStyle;
  21.     private $periodAlign;
  22.  
  23.     protected $dPeriod;
  24.     protected $series;
  25.     protected $updating;
  26.     protected $canUsePeriod;
  27.  
  28.     public $SingleSource;
  29.     public $HideSourceList;
  30.     public $noSourceRequired// For "Custom" function
  31.  
  32.  
  33.     // Interceptors
  34.     function __get$property {
  35.       $method ="get{$property}";
  36.       if method_exists$this$method ) ) {
  37.         return $this->$method();
  38.       }
  39.     }
  40.  
  41.     function __set $property,$value {
  42.       $method ="set{$property}";
  43.       if method_exists$this$method ) ) {
  44.         return $this->$method($value);
  45.       }
  46.     }
  47.  
  48.     public function Functions($c=null{
  49.         parent::__construct($c);
  50.         
  51.         $this->initFields();
  52.     }
  53.  
  54.     private function initFields({
  55.         $this->canUsePeriod = true;
  56.  
  57.         $this->periodStyle PeriodStyle::$NUMPOINTS;
  58.         $this->periodAlign PeriodAlign::$CENTER;
  59.     }
  60.  
  61.     protected function readResolve({
  62.         $this->initFields();
  63.         return $this;
  64.     }
  65.  
  66.     public function newInstance($f/* tODO throw IllegalAccessException,
  67.                         InstantiationException*/ {
  68.                 return $f->newInstance();
  69.         }
  70.  
  71.         /**
  72.           * Controls how many points or X range will trigger a new point
  73.           * calculation.<br>
  74.           * Zero means all source points.<br>
  75.           * For example, Average function uses the Period property to calculate a
  76.           * new average point each time the "Period" number of points or X range is
  77.           * exceed. <br><br>
  78.           * <b>NOTE:</b> You may switch between number of points or X range by using
  79.           * the Function PeriodStyle property. <br>
  80.           * Default value: 0D
  81.           *
  82.           * @return double 
  83.           */
  84.     public function getPeriod({
  85.         return $this->dPeriod;
  86.     }
  87.  
  88.     public function setPeriod($value{
  89.         /** @todo ELIMINATE EXCEPTION HERE ! */
  90. //        if (value < 0) {
  91. //            throw new TeeChartException(Language.getString("FunctionPeriod"));
  92. //        }
  93.         if ($this->dPeriod != $value{
  94.             $this->dPeriod = $value;
  95.             $this->recalculate();
  96.         }
  97.     }
  98.  
  99.         /**
  100.           * Returns the Series parent of Function.<br>
  101.           * Run-time and read only. <br>
  102.           * The Series property returns the Series parent of this Function.<br>
  103.           * TChart uses Series to do the actual drawing.
  104.           *
  105.           * @return Series 
  106.           */
  107.     public function getSeries({
  108.         return $this->series;
  109.     }
  110.  
  111.     public function setSeries($value{
  112.         if ($this->series != $value{
  113.  
  114.             if ($this->series != null)
  115.               $this->series->setFunction(null);
  116.             $this->series = $value;
  117.             if ($value != null)
  118.               $value->setFunction($this);
  119.         }
  120.     }
  121.  
  122.         /**
  123.           * Controls how the Period property is interpreted.<br>
  124.           * Either as number of points or as range.<br>
  125.           * Range means Period property is specified in a range of values. <br>
  126.           * Being able to define Period as a range can be very useful when using
  127.           * Date-Time series and when you want to express the  Period  of the
  128.           * function in a date-time step like  OneMonth  or  OneDay.<br>
  129.           * So, for example you can now plot the monthly average of sales function
  130.           * just using a normal Average function on a date-time source series and
  131.           * setting the function period to one month :<br>
  132.           * { Place a series1 and fill it with datetime data values at runtime
  133.           * (or from a database) } <br>
  134.           * series2.setFunction( new Average() ); <br>
  135.           * series2.getFunction().setPeriodStyle( Range); series2.getFunction().setPeriod(
  136.           * DateTimeStep[ dtOneMonth ]); series2.setDataSource(series1);<br><br>
  137.           * This will result in several points, each one showing the  average of
  138.           * each month of data in Series1. <br>
  139.           * It's mandatory that points in the source Series1 should be sorted by
  140.           * date when calculating functions on datetime periods. <br><br>
  141.           * The range can also be used for non-datetime series: <br><br>
  142.           * series2.setFunction( new Average() ) ; <br>
  143.           * series2.getFunction().setPeriodStyle(Range); <br>
  144.           * series2.getFunction().setPeriod(100); <br>
  145.           * series2.setDataSource(series1) ; <br>>br>
  146.           * This will calculate an average for each group of points inside every
  147.           * 100 interval. <br><br>
  148.           * (Points with X >=0, X<100 will be used to calculate the first average,
  149.           * points with X >=100, X<200 will be used to calculate the second average
  150.           * and so on... ) <br>
  151.           * Notice this is different than calculating an average for every 100
  152.           * points. <br>
  153.           * Default value: PeriodStyle.NumPoints
  154.           *
  155.           *
  156.           * @return PeriodStyle 
  157.           */
  158.     public function getPeriodStyle({
  159.         return $this->periodStyle;
  160.     }
  161.  
  162.     public function setPeriodStyle($value{
  163.         if ($this->periodStyle != $value{
  164.             $this->periodStyle $value;
  165.             $this->recalculate();
  166.         }
  167.     }
  168.  
  169.         /**
  170.           * Controls where to place function calculations inside the full period
  171.           * space.<br>
  172.           * The position of calculation output points within range.<br>
  173.           * When the function Period is greater than zero (so it calculates by
  174.           * groups of points), the function results are added to the series by
  175.           * default at the center position of the Function Period. You can change
  176.           * this by setting PeriodAlign to  <br><br>
  177.           * - First (function result will be added to series at start of each
  178.           * period),  <br>
  179.           * - Center (function result will be added to series at center of each
  180.           * period) <br>
  181.           * - Last (function result will be added to series at end of each period)
  182.           * <br><br>
  183.           * Example <br><br>
  184.           * <code>function1.setPeriodAlign(Center);
  185.           * // <-- by default is centered</code> <br>
  186.           * The  First  and  Last  constants will plot calculations at the start and
  187.           * end  X  coordinates of each  Period .<br>
  188.           * Default value: PeriodAlign.Centre
  189.           *
  190.           *
  191.           * @return PeriodAlign 
  192.           */
  193.     public function getPeriodAlign({
  194.         return $this->periodAlign;
  195.     }
  196.  
  197.     public function setPeriodAlign($value{
  198.         if ($this->periodAlign != $value{
  199.             $this->periodAlign $value;
  200.             $this->recalculate();
  201.         }
  202.     }
  203.  
  204.     protected function addFunctionXY($yMandatorySource$tmpX$tmpY{
  205.         if ($yMandatorySource{
  206.             $this->series->addXY($tmpX$tmpY);
  207.         else {
  208.             $this->series->addXY($tmpY$tmpX);
  209.         }
  210.     }
  211.  
  212.     // MS : added to allow overrides in curve fitting functions
  213.     protected function calculatePeriod($source$tmpX$firstIndex$lastIndex{
  214.         $this->addFunctionXY($source->getYMandatory()$tmpX,
  215.                       $this->calculate($source$firstIndex$lastIndex));
  216.     }
  217.  
  218.         // abstract
  219.         /**
  220.           * Performs function operation on SourceSeries series.<br>
  221.           * First and Last parameters are ValueIndex of first and last point used
  222.           * in calculation. <br>
  223.           * You can override Calculate function to perform customized calculation
  224.           * on one SourceSeries.
  225.           *
  226.           * @param source Series
  227.           * @param first int
  228.           * @param last int
  229.           * @return double 
  230.           */
  231.     public function calculate($source$first$last{
  232.         return 0;
  233.     }
  234.  
  235.         // abstract
  236.         /**
  237.           * Performs function operation on list of series (SourceSeriesList).<br>
  238.           * The ValueIndex parameter defines ValueIndex of point in each Series in
  239.           * list. <br>
  240.           * You can override CalculateMany function to perform customized
  241.           * calculation on list of SourceSeries.
  242.           *
  243.           * @param sourceSeries ArrayList
  244.           * @param valueIndex int
  245.           * @return double 
  246.           */
  247.     public function calculateMany($sourceSeries$valueIndex{
  248.         return 0;
  249.     }
  250.  
  251.     // MS : added to allow overrides in curve fitting functions
  252.     protected function calculateAllPoints($source$notMandatorySource{
  253.                 $tmpY $this->calculate($source-1-1);
  254.  
  255.                 if (!$this->series->getAllowSinglePoint()) {
  256.                         $tmpX $notMandatorySource->getMinimum();
  257.                         $this->addFunctionXY($source->getYMandatory()$tmpX$tmpY);
  258.                         $tmpX $notMandatorySource->getMaximum();
  259.                         $this->addFunctionXY($source->getYMandatory()$tmpX$tmpY);
  260.                 else
  261.                 /* centered point */
  262.                 if ((!$source->getYMandatory()) && $this->series->getYMandatory()) {
  263.                         $tmpX $notMandatorySource->getMinimum(+
  264.                                       0.5 $notMandatorySource->getRange();
  265.                         $this->series->addXY($tmpX$tmpY);
  266.                 else {
  267.                         $tmpX $notMandatorySource->getMinimum(+
  268.                                       0.5 $notMandatorySource->getRange();
  269.                         if ($this->series->getYMandatory()) {
  270.                                 $this->addFunctionXY($source->getYMandatory()$tmpX$tmpY);
  271.                         else {
  272.                                 $this->series->addXY($tmpY$tmpX);
  273.                         }
  274.                 }
  275.         }
  276.  
  277.     protected function calculateByPeriod($source$notMandatorySource{
  278.          $tmpFirst 0;
  279.          $tmpCount $source->getCount();
  280.          $tmpBreakPeriod $notMandatorySource->value[$tmpFirst];
  281.          $tmpStep DateTimeStep::find($this->dPeriod);
  282.  
  283.          do {
  284.             $posLast 0;
  285.             if ($this->periodStyle == PeriodStyle::$NUMPOINTS{
  286.                 $tmpLast $tmpFirst MathUtils::round($this->dPeriod1;
  287.                 $posFirst $notMandatorySource->value[$tmpFirst];
  288.  
  289.                 if ($tmpLast $tmpCount{
  290.                     $posLast $notMandatorySource->value[$tmpLast];
  291.                 }
  292.             else {
  293.                 $tmpLast $tmpFirst;
  294.                 $posFirst $tmpBreakPeriod;
  295.  
  296.                 /** @todo FINISH !! */
  297. //                tmpBreakPeriod = series.horizAxis().IncDecDateTime(true,
  298. //                        tmpBreakPeriod, dPeriod, tmpStep);
  299.  
  300.  
  301.                 $posLast $tmpBreakPeriod ($this->dPeriod * 0.001);
  302.  
  303.                 while ($tmpLast $tmpCount 1{
  304.                     if ($notMandatorySource->value[$tmpLast 1$tmpBreakPeriod{
  305.                         $tmpLast++;
  306.                     else {
  307.                         break;
  308.                     }
  309.                 }
  310.             }
  311.             $tmpCalc false;
  312.  
  313.             if ($tmpLast $tmpCount{
  314.  
  315.                 /* align periods */
  316.                 if ($this->periodAlign == PeriodAlign::$FIRST{
  317.                     $tmpX $posFirst;
  318.                 else
  319.                 if ($this->periodAlign == PeriodAlign::$LAST{
  320.                     $tmpX $posLast;
  321.                 else {
  322.                     $tmpX ($posFirst $posLast0.5;
  323.                 }
  324.  
  325.                 if (($this->periodStyle == PeriodStyle::$RANGE&&
  326.                     ($this->notMandatorySource->value[$tmpFirst$tmpBreakPeriod)) {
  327.                     $tmpCalc true;
  328.                 }
  329.  
  330.                 if (($this->periodStyle == PeriodStyle::$NUMPOINTS|| $tmpCalc{
  331.                     $this->calculatePeriod($source$tmpX$tmpFirst$tmpLast);
  332.                 else {
  333.                     $this->addFunctionXY($source->getYMandatory()$tmpX0);
  334.                 }
  335.             }
  336.             if (($this->periodStyle == PeriodStyle::$NUMPOINTS|| $tmpCalc{
  337.                 $tmpFirst $tmpLast 1;
  338.             }
  339.         while ($tmpFirst <= $tmpCount 1);
  340.     }
  341.  
  342.         /**
  343.           * Gets descriptive text.
  344.           *
  345.           * @return String 
  346.           */
  347.     public function getDescription({
  348.         return Language::getString("GalleryFunctions");
  349.     }
  350.  
  351.     protected function doCalculation($source$notMandatorySource{
  352.         if ($this->dPeriod == 0{
  353.             $this->calculateAllPoints($source$notMandatorySource);
  354.         else {
  355.             $this->calculateByPeriod($source$notMandatorySource);
  356.         }
  357.     }
  358.  
  359.     protected function valueList($s{
  360.         $tmp ($this->series != null$this->series->getMandatory()->getDataMember("";
  361.         if (strlen($tmp== 0{
  362.             return $s->getMandatory();
  363.         else {
  364.             return $s->getValueList($tmp);
  365.         }
  366.     }
  367.  
  368.     private function calculateFunctionMany($source{
  369.  
  370.         $s $source[0];
  371.         $xList $s->getNotMandatory();
  372.  
  373.         // Find datasource with bigger number of points... 5.02
  374.         for $t 0$t sizeof($source)$t++{
  375.              $o $source[$t];
  376.             if (($o != null&& ($o->getCount($s->getCount())) {
  377.                 $s $o;
  378.                 $xList $s->getNotMandatory();
  379.             }
  380.  
  381.             // use source to calculate points...
  382.             if ($xList != null{
  383.                 $tmpList Array();
  384.  
  385.                 for $tt 0$tt sizeof($source)$tt++{
  386.                     $tmpList[]=$source[$tt];
  387.                 }
  388.  
  389.                 for $tt 0$tt $s->getCount()$tt++{
  390.                     $tmpX $xList->value[$tt];
  391.                     $tmpY $this->calculateMany($tmpList$tt);
  392.  
  393.                     if (!$s->getYMandatory()) // $this->swap
  394.                         $tmp $tmpX;
  395.                         $tmpX $tmpY;
  396.                         $tmpY $tmp;
  397.                     }
  398.  
  399.                     $this->series->addXYText($tmpX$tmpY$s->getLabels($tt));
  400.                 }
  401.             }
  402.         }
  403.     }
  404.  
  405.         /**
  406.           * Gets all points from Source series, performs a function operation and
  407.           * stores results in ParentSeries.<br>
  408.           *
  409.           * @param source ArrayList
  410.           */
  411.     public function addPoints($source{
  412.         if (!$this->updating// 5.02
  413.             if ($source != null{
  414.                 if (sizeof($source1{
  415.                     $this->calculateFunctionMany($source);
  416.                 else {
  417.                     if (sizeof($source0{
  418.                          $s $source[0];
  419.                         if ($s->getCount(0{
  420.                             $this->doCalculation($s$s->getNotMandatory());
  421.                         }
  422.                     }
  423.                 }
  424.             }
  425.         }
  426.     }
  427.  
  428.     private function beginUpdate({
  429.         $this->updating = true;
  430.     }
  431.  
  432.     private function endUpdate({
  433.         if ($this->updating{
  434.             $this->updating = false;
  435.             $this->recalculate();
  436.         }
  437.     }
  438.  
  439.         /**
  440.           * Performs a checkDataSource method call on parent Series.<br>
  441.           * Basically, all points in parent Series are recalculated.<br>
  442.           * The recalculating is performed only if internal updating flag is set to
  443.           * false.<br>
  444.           * To make sure updating is set to false, you can call Function
  445.           * endUpdate() method prior to calling Function recalculate.
  446.           */
  447.     public function recalculate({
  448.         if ((!$this->updating&& ($this->series != null)) {
  449.             $this->series->checkDataSource();
  450.         }
  451.     }
  452.  
  453.     public function clear(){
  454.         /** Does nothing, used only by Bollinger and Stochastic **/
  455.     }
  456. }
  457. ?>

Documentation generated on Wed, 16 Jun 2010 12:05:26 +0200 by phpDocumentor 1.4.1