Subversion Repositories Applications.gtt

Rev

Rev 61 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/*
 * This work is hereby released into the Public Domain.
 * To view a copy of the public domain dedication,
 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
 *
 */

require_once dirname(__FILE__)."/Component.class.php";

/**
 * A mathematic function
 *
 * @package Artichow
 */
class awMathFunction implements awLegendable {

        /**
         * Function line
         *
         * @var Line
         */
        public $line;
        
        /**
         * Marks for your plot
         *
         * @var Mark
         */
        public $mark;
        
        /**
         * Callback function
         *
         * @var string
         */
        public $f;
        
        /**
         * Start the drawing from this value
         *
         * @var float
         */
        public $fromX;
        
        /**
         * Stop the drawing at this value
         *
         * @var float
         */
        public $toX;

        /**
         * Line color
         *
         * @var Color
         */
        protected $color;
        
        /**
         * Construct the function
         *
         * @param string $f Callback function
         * @param float $fromX
         * @param float $toX
         */
        public function __construct($f, $fromX = NULL, $toX = NULL) {
        
                $this->f = (string)$f;
                $this->fromX = is_null($fromX) ? NULL : (float)$fromX;
                $this->toX = is_null($toX) ? NULL : (float)$toX;
                
                $this->line = new awLine;
                $this->mark = new awMark;
                $this->color = new awBlack;
        
        }
        
        /**
         * Change line color
         *
         * @param awColor $color A new awcolor
         */
        public function setColor(awColor $color) {
                $this->color = $color;
        }
        
        /**
         * Get line color
         *
         * @return Color
         */
        public function getColor() {
                return $this->color;
        }

        /**
         * Get the background color or gradient of an element of the component
         *
         * @return Color, Gradient
         */
        public function getLegendBackground() {
        }

        /**
         * Get the line thickness
         *
         * @return NULL
         */
        public function getLegendLineThickness() {
                return $this->line->getThickness();
        }

        /**
         * Get the line type
         *
         * @return NULL
         */
        public function getLegendLineStyle() {
                return $this->line->getStyle();
        }

        /**
         * Get the color of line
         *
         * @return NULL
         */
        public function getLegendLineColor() {
                return $this->color;
        }

        /**
         * Get a mark object
         *
         * @return NULL
         */
        public function getLegendMark() {
                return $this->mark;
        }

}

registerClass('MathFunction');
 
/**
 * For mathematics functions
 *
 * @package Artichow
 */
class awMathPlot extends awComponent {
        
        /**
         * Functions
         *
         * @var array
         */
        protected $functions = array();
        
        /**
         * Grid properties
         *
         * @var Grid
         */
        public $grid;
        
        /**
         * X axis
         *
         * @var Axis
         */
        public $xAxis;
        
        /**
         * Y axis
         *
         * @var Axis
         */
        public $yAxis;
        
        /**
         * Extremum
         *
         * @var Side
         */
        private $extremum = NULL;
        
        /**
         * Interval
         *
         * @var float
         */
        private $interval = 1;
        
        /**
         * Build the plot
         *
         * @param int $xMin Minimum X value
         * @param int $xMax Maximum X value
         * @param int $yMax Maximum Y value
         * @param int $yMin Minimum Y value
         */
        public function __construct($xMin, $xMax, $yMax, $yMin) {
        
                parent::__construct();
                
                $this->setPadding(8, 8, 8, 8);
                
                $this->grid = new awGrid;
                
                // Hide grid by default
                $this->grid->hide(TRUE);
                
                // Set extremum
                $this->extremum = new awSide($xMin, $xMax, $yMax, $yMin);
                
                // Create axis
                $this->xAxis = new awAxis;
                $this->xAxis->setTickStyle(awTick::IN);
                $this->xAxis->label->hideValue(0);
                $this->initAxis($this->xAxis);
                
                $this->yAxis = new awAxis;
                $this->yAxis->setTickStyle(awTick::IN);
                $this->yAxis->label->hideValue(0);
                $this->initAxis($this->yAxis);
                
        }
        
        protected function initAxis(awAxis $axis) {
        
                $axis->setLabelPrecision(1);
                $axis->addTick('major', new awTick(0, 5));
                $axis->addTick('minor', new awTick(0, 3));
                $axis->addTick('micro', new awTick(0, 1));
                $axis->setNumberByTick('minor', 'major', 1);
                $axis->setNumberByTick('micro', 'minor', 4);
                $axis->label->setFont(new awTuffy(7));
                
        }
        
        /**
         * Interval to calculate values
         *
         * @param float $interval
         */
        public function setInterval($interval) {
                $this->interval = (float)$interval;
        }
        
        /**
         * Add a formula f(x)
         *
         * @param awMathFunction $function
         * @param string $name Name for the legend (can be NULL if you don't want to set a legend)
         * @param int $type Type for the legend
         */
        public function add(awMathFunction $function, $name = NULL, $type = awLegend::LINE) {
        
                $this->functions[] = $function;
                
                if($name !== NULL) {
                        $this->legend->add($function, $name, $type);
                }
        
        }
        
        public function init(awDriver $driver) {
                
                list($x1, $y1, $x2, $y2) = $this->getPosition();
                
                $this->xAxis->line->setX($x1, $x2);
                $this->xAxis->label->setAlign(NULL, awLabel::BOTTOM);
                $this->xAxis->label->move(0, 3);
                $this->xAxis->setRange($this->extremum->left, $this->extremum->right);
                
                $this->yAxis->line->setY($y2, $y1);
                $this->yAxis->label->setAlign(awLabel::RIGHT);
                $this->yAxis->label->move(-6, 0);
                $this->yAxis->reverseTickStyle();
                $this->yAxis->setRange($this->extremum->bottom, $this->extremum->top);
                
                
                $this->xAxis->setYCenter($this->yAxis, 0);
                $this->yAxis->setXCenter($this->xAxis, 0);
                
                if($this->yAxis->getLabelNumber() === NULL) {
                        $number = $this->extremum->top - $this->extremum->bottom + 1;
                        $this->yAxis->setLabelNumber($number);
                }
                
                if($this->xAxis->getLabelNumber() === NULL) {
                        $number = $this->extremum->right - $this->extremum->left + 1;
                        $this->xAxis->setLabelNumber($number);
                }
                
                // Set ticks
                
                $this->xAxis->tick('major')->setNumber($this->xAxis->getLabelNumber());
                $this->yAxis->tick('major')->setNumber($this->yAxis->getLabelNumber());
                
                                
                // Set axis labels
                $labels = array();
                for($i = 0, $count = $this->xAxis->getLabelNumber(); $i < $count; $i++) {
                        $labels[] = $i;
                }
                $this->xAxis->label->set($labels);
                
                $labels = array();
                for($i = 0, $count = $this->yAxis->getLabelNumber(); $i < $count; $i++) {
                        $labels[] = $i;
                }
                $this->yAxis->label->set($labels);
        
                parent::init($driver);
                
                // Create the grid
                $this->createGrid();
        
                // Draw the grid
                $this->grid->draw($driver, $x1, $y1, $x2, $y2);
                
        }
        
        public function drawEnvelope(awDriver $driver) {
                
                // Draw axis
                $this->xAxis->draw($driver);
                $this->yAxis->draw($driver);
        
        }
        
        public function drawComponent(awDriver $driver, $x1, $y1, $x2, $y2, $aliasing) {
        
                foreach($this->functions as $function) {
                
                        $f = $function->f;
                        $fromX = is_null($function->fromX) ? $this->extremum->left : $function->fromX;
                        $toX = is_null($function->toX) ? $this->extremum->right : $function->toX;
                        
                        $old = NULL;
                        
                        for($i = $fromX; $i <= $toX; $i += $this->interval) {
                        
                                $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($i, $f($i)));
                                
                                if($p->y >= $y1 and $p->y <= $y2) {
                                        $function->mark->draw($driver, $p);
                                }
                        
                                if($old !== NULL) {
                                
                                        $line = $function->line;
                                        $line->setLocation($old, $p);
                                
                                        if(
                                                ($line->p1->y >= $y1 and $line->p1->y <= $y2) or
                                                ($line->p2->y >= $y1 and $line->p2->y <= $y2)
                                        ) {
                                                $driver->line(
                                                        $function->getColor(),
                                                        $line
                                                );
                                        }
                                
                                }
                                
                                $old = $p;
                        
                        }
                        
                        // Draw last point if needed
                        if($old !== NULL and $i - $this->interval != $toX) {
                        
                                $p = awAxis::toPosition($this->xAxis, $this->yAxis, new awPoint($toX, $f($toX)));
                                
                                if($p->y >= $y1 and $p->y <= $y2) {
                                        $function->mark->draw($driver, $p);
                                }
                                
                                
                                $line = $function->line;
                                $line->setLocation($old, $p);
                                
                                if(
                                        ($line->p1->y >= $y1 and $line->p1->y <= $y2) or
                                        ($line->p2->y >= $y1 and $line->p2->y <= $y2)
                                ) {
                                        $driver->line(
                                                $function->getColor(),
                                                $line
                                        );
                                }
                                
                        }
                
                }
        
        }
        
        protected function createGrid() {
                
                // Horizontal lines of the grid

                $major = $this->yAxis->tick('major');
                $interval = $major->getInterval();
                $number = $this->yAxis->getLabelNumber() - 1;
                
                $h = array();
                if($number > 0) {
                        for($i = 0; $i <= $number; $i++) {
                                $h[] = $i / $number;
                        }
                }
                
                // Vertical lines
        
                $major = $this->xAxis->tick('major');
                $interval = $major->getInterval();
                $number = $this->xAxis->getLabelNumber() - 1;
                
                $w = array();
                if($number > 0) {
                        for($i = 0; $i <= $number; $i++) {
                                if($i%$interval === 0) {
                                        $w[] = $i / $number;
                                }
                        }
                }
        
                $this->grid->setGrid($w, $h);
        
        }

}

registerClass('MathPlot');
?>