PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Mon Sep 28, 2020 12:21 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: GD Math Function Graphs
PostPosted: Sun Aug 13, 2006 9:31 am 
Offline
Forum Contributor
User avatar

Joined: Sun May 07, 2006 5:19 am
Posts: 101
This is my first and only script using GD because I am usually a non-graphical person. Anyhow, what this script does is it will plot the graph of any mathematical function. The function can be explicit [ y = f(x) ] or parametric [ x = g(t); y = f(t) ].

I started doing this as a direct web application but then converted it to PHP5 OOP for my convinience, with the classes 'graph', and 'locus'. I also managed to make a 'tangent' class yesterday to draw a tangent at any point of a given graph.

The dimensions of the graph and properties of the functional relation can be highly customized... at least that was the main aim of it.

It hasn't been documented very properly, but I hope you can understand my comments.

The Script:

Syntax: [ Download ] [ Hide ]
<?php

/*

GD Math Function Graphs

Plot graphs and tangents of explicit and parametric relations

Made by Verminox

Classes: graph, locus, tangent

*/




//Constants

define('pi',M_PI);

define('e',M_E);

define('h',0.001);



//Commonly used functions that are not pre-built

function ln($x){

        return log($x);

}



function sec($x){

        return 1/cos($x);

}



function cosec($x){

        return 1/sin($x);

}



function cot($x){

        return 1/tan($x);

}



function asec($x){

        return 1/acos($x);

}



function acosec($x){

        return 1/sin($x);

}



function acot($x){

        return 1/atan($x);

}



/* Main Graph Class */



class graph {



        private $img; //The GD image resource

       

        public  $width,    $height;    //In Pixels

        public  $min_x,    $max_x;    //Limits of the X-axis in Units

        public  $min_y,    $max_y;    //Limits of the X-axis in Units

        public  $scale_x,  $scale_y;   //Measured in Pixels per Unit   

        public  $grid    = true;       //Whether or not to mark a unit-wise grid

        private $total_x,  $total_y;   //No. of units. Used internally only

        private $legend_y = 25;        //Offset from top of graph to mark legend

                   

        private $colors = array();     //Colors alloted to the image

       

        public function __construct($min_x,$max_x,$min_y,$max_y,$scale_x,$scale_y){

                $this->min_x = $min_x;

                $this->max_x = $max_x;

                $this->min_y = $min_y;

                $this->max_y = $max_y;

                $this->scale_x = $scale_x;

                $this->scale_y = $scale_y;

               

                //Validate

                if ( $this->min_x >= $this->max_x || $this->min_y >= $this->max_y ){

                        die("Error! Incorrect range for either X axis or Y axis");

                }

               

                //Set Variables

                $this->total_x = $this->max_x   - $this->min_x;

                $this->total_y = $this->max_y   - $this->min_y;

                $this->width   = $this->total_x * $this->scale_x;

                $this->height  = $this->total_y * $this->scale_y;

       

                //Create

                $this->img = @imagecreatetruecolor($this->width,$this->height) or die('Cannot Initialize new GD image stream');

               

                //Colors

                $this->colors['black']    = imagecolorallocate($this->img, 0, 0, 0);

                $this->colors['white']    = imagecolorallocate($this->img, 255, 255, 255);

                $this->colors['red']      = imagecolorallocate($this->img, 255, 0, 0);

                $this->colors['blue']     = imagecolorallocate($this->img, 0, 0, 255);

                $this->colors['orange']   = imagecolorallocate($this->img, 210, 90, 0);

                $this->colors['green']    = imagecolorallocate($this->img, 0, 128, 0);

                $this->colors['purple']   = imagecolorallocate($this->img, 128, 0, 128);

                $this->colors['grey']     = imagecolorallocate($this->img, 204, 204, 204);

               

                //Main Fill

                imagefill($this->img,0,0,$this->colors['white']);

               

                //Grid and Marking: X-axis

                for (  $unit_x = floor($this->min_x) + 1; $unit_x < $this->max_x; $unit_x++ ){

                        $pixel_x = $this->unit2pixel_x($unit_x);

                        if($this->grid) imageline($this->img, $pixel_x, 0, $pixel_x, $this->height, $this->colors['grey']);

                        imagestring($this->img, 1, $pixel_x-5, 10, $unit_x, $this->colors['black']);

                        imagestring($this->img, 1, $pixel_x-5, $this->height-20, $unit_x, $this->colors['black']);

                }      

               

                //Grid and Marking: Y-axis     

                for (  $unit_y = floor($this->min_y) + 1; $unit_y < $this->max_y; $unit_y++ ){

                        $pixel_y = $this->unit2pixel_y($unit_y);

                        if($this->grid) imageline($this->img, 0, $pixel_y, $this->width, $pixel_y, $this->colors['grey']);

                        imagestring($this->img, 1, 10, $pixel_y-5, $unit_y, $this->colors['black']);

                        imagestring($this->img, 1, $this->width-20, $pixel_y-5, $unit_y, $this->colors['black']);

                }

               

                //Border and axes go later because they have to overwrite any grid lines that coincide

               

                //Draw Border

                imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$this->colors['black']);

               

                //X-axis

                imageline($this->img,0,$this->unit2pixel_y(0),$this->width,$this->unit2pixel_y(0),$this->colors['black']);

                //Y-axis

                imageline($this->img,$this->unit2pixel_x(0),0,$this->unit2pixel_x(0),$this->height,$this->colors['black']);

               

        }

       

        //Conversions

        private function unit2pixel_x($unit){

                $pixel = ($unit - $this->min_x) * $this->scale_x;

                return $pixel;

        }

       

        private function unit2pixel_y($unit){

                $pixel = ($this->max_y - $unit) * $this->scale_y;

                return $pixel;

        }

       

        private function pixel2unit_x($pixel){

                $unit = $this->min_x + ($pixel / $this->scale_x);

                return $unit;

        }

       

        private function pixel2unit_y($pixel){

                $unit = $this->max_y - ($pixel / $this->scale_y);

                return $unit;

        }

       

        //Plotting a Locus

        public function plot($locus){

                //Draw a colored box with the equation(s) of the locus (unless $locus->legend is false)

                if($locus->legend){

                        imagefilledrectangle($this->img,25,$this->legend_y,40,$this->legend_y+10,$this->colors[$locus->color]);

                        imagestring($this->img, 2, 45,$this->legend_y, $locus->express(), $this->colors[$locus->color]);

                        $this->legend_y += 15;

                }

               

                /*

                This is the main loop.

                We will assume a parameter $t to vary between the limits of the locus

                If the locus is parametric, it will be in the form of:

                     x = g(t);

                         y = f(t);

            If the locus is explicit, it will be in the form of:

                     x = g(t) = t;

                         y = f(t) = f(x);

                So $x can also be a variable in the equation for $y if $x==$t

                Now, for each value of $t, we will get the value for $x and $y in Units.

                Then we will convert this value into the absolute pixel value based on the

                dimensions of the graph which are done by the conversion functions defined above.

                A single point corresponding to the co-ordinates will then be plotted.

                */


               

                for($t = $locus->min; $t <= $locus->max; $t += $locus->increment){             

                        $x = @$locus->g($t);

                        $y = @$locus->f($t);

                        if ( $x === NULL || $x === false || $y === NULL || $y === false ){ continue; }

                        $pixel_x = $this->unit2pixel_x($x);

                        $pixel_y = $this->unit2pixel_y($y);

                        if ( $pixel_y < 0 || $pixel_y > $this->height || $pixel_x < 0 || $pixel_x > $this->width ){

                                continue;

                        }

                        imagesetpixel($this->img,$pixel_x,$pixel_y,$this->colors[$locus->color]);                      

                }

        }

       

        //Create the image as PNG

        public function draw($filename = NULL){

                if( $filename ) {

                        return imagepng($this->img,$filename);

                } else {

                        header("Content-type: image/png");

                        header("Pragma: No-cache");

                        return imagepng($this->img);

                }

        }

       

        //The image can be destroyed either manually...

        public function destroy(){

                imagedestroy($this->img);

        }

       

        //...or automatically at the end of script execution. So there will never be a memory overload.

        public function __destruct(){

                @imagedestroy($this->img);

        }

       

}



/* Main Locus Class; Both Explicit and Parametric */



class locus {

       

        public $x = 't'; //Equation for x = g(t)

        public $y = '0'; //Equation for y = f(t). Note: y can also be f(x) if x==t, i.e Explicit relation

        public $color = 'black'; //Key for graph::colors[]

        public $min = -10; //Min value for t

        public $max = 10;  //Max value for t

        public $increment = 0.01; //&#948;t i.e small increment in t during the loop for graph::plot()

        public $legend = true; //Whether or not to display a legend at the top left of the graph

       

        //Regexp pattern used in self::interpret()

        const VAR_PATTERN = '/([\s\(\)\[\]\,\^\*\/\+\-\d])(x|t)([\s\(\)\[\]\,\^\*\/\+\-\d])/';

       

       

        const EXPLICIT = 't'; //Used in locus::construct() if explicit

        //For example: $var = new locus(locus::EXPLICIT, 'sin(x)');

       

       

        //Constructor. First param can be locus::EXPLICIT if $y is a function of x.

        public function __construct($x='t',$y='0'){

                $this->x = $x;

                $this->y = $y;

        }

       

        //Change short hand terms in the equation to PHP-valid syntax

        public static function interpret($equation){

                $equation = self::pad($equation);              

               

                //Change 't' to '$t'. In case of explicit, change 'x' to '$t' as well since $x==$t.

                $equation = preg_replace(self::VAR_PATTERN,"$1\$t$3",$equation);

               

                //Shorthand exponential terms. Not for use with complex expressions. Stuff like e^x allowed.

                //For complex terms, use pow() instead

                $equation = preg_replace('/([^\s\(\,]+)\^([^\s\)\,]+)/',"pow($1,$2)",$equation);       

               

                //Change '2x' to '2*x' and '(x+1)(x+2)' into '(x+1)*(x+2)', etc.

                $equation = preg_replace('/([\d\)])([\$\(a-z])/',"$1*$2",$equation);

               

                return $equation;

        }

       

        //Add whitespace at the ends for matching with self::VAR_PATTERN

        protected static function pad($str){

                return ' ' . $str . ' ';

        }

       

        //For use in legends

        public function express(){

                return 'x = ' . $this->x . '; y = ' . $this->y . '; ';

        }      

       

        //x = g(t)

        public function g($t){

                $exp = self::interpret(self::pad($this->x));

                eval("\$value = $exp;");

                return $value;

        }

       

        //y = f(t)

        public function f($t){

                $exp = self::interpret(self::pad($this->y));           

                eval("\$value = $exp;");

                return $value;

        }

       

        //Self-explanatory

        public function is_parametric(){

                return (trim($this->x) !== 't');

        }

       

        //Alias of $graph->plot($this)

        public function plot_on(&$graph){

                $graph->plot($this);

        }

       

}





/* Class for constructing a tangent to a given locus at a given point */



class tangent extends locus {

       

        public function __construct(&$locus,$t){

                //Finding the derivative                                       

                $dy = $locus->f($t+h) - $locus->f($t); 

                $dx = $locus->g($t+h) - $locus->g($t);

                //m = dy/dx => Slope of tangent

                $m = ( $dy ) / ( $dx );

                //Point of contact of tangent

                $x1 = $locus->g($t);

                $y1 = $locus->f($t);

               

                /*

                Now, we have the slope of the tangent, and point of contact.

                By the slope-point form, its equation is

                    (y - y1) = m(x - x1)

                 => y = m(x - x1) + y1

                Note that here $m, $x and $y are passed as values instead of variables. The single 'x' part gets interpretted later on while plotting the graph to varying values of $x = $t

                */


                $this->y = "( $m * ( x - $x1) ) + $y1";

               

                $this->legend = false; //Not really needed for a tangent, but can be manually changed

        }

       

}

?>




Implementation:

Syntax: [ Download ] [ Hide ]
<?php

//Create a graph with scale of 40 pixels per unit

$graph = new graph(-10,10,-10,10,40,40);



//Circle with radius = 5 Units

$circle = new locus('5 * cos(t)','5 * sin(t)');

$circle->min = 0;

$circle->max =  2*pi;

$circle->color = 'red';

$circle->increment = 0.005;

$graph->plot($circle);



//Tangent to the above circle at t = pi/4 [i.e about 45 degrees]

$tangent = new tangent($circle,M_PI/4);

$tangent->color = 'green';

$graph->plot($tangent);



//Sine wave

$trig = new locus(locus::EXPLICIT,'sin(x)');

$trig->color = 'blue';

$graph->plot($trig);



//Exponential curve

$exp = new locus(locus::EXPLICIT,'e^x');

$exp->color = 'purple';

$graph->plot($exp);



//Draw graph

$graph->draw();



//Free memory

$graph->destroy();



?>




Syntax: [ Download ] [ Hide ]
<?php

//Create a graph with scale of 40 pixels per unit

$graph = new graph(-10,10,-10,10,40,40);



//Butterfly Curve

$butterfly = new locus(

                        'sin(t) * ( pow(e,cos(t)) - 2cos(4t) - pow(sin(t/12),5) )',

                        'cos(t) * ( pow(e,cos(t)) - 2cos(4t) - pow(sin(t/12),5) )' );

$butterfly->min = -100;

$butterfly->max = 100;

$butterfly->increment = 0.01;

$butterfly->color = 'red';

$graph->plot($butterfly);



$graph->draw();



$graph->destroy();

?>




Note: I am posting links the the image files rather than the PHP script because I want to save bandwidth. Also, I cannot upload this anywhere because my host does not support PHP5.

Does anybody know any free host that supports PHP5 so that I can show a working version to those who do not have PHP installed locally?

Criticism is greatly appreciated :)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 13, 2006 12:24 pm 
Offline
DevNet Master
User avatar

Joined: Mon Oct 25, 2004 9:29 pm
Posts: 3698
Location: New Jersey, US


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 13, 2006 12:47 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 12:30 am 
Offline
Forum Contributor
User avatar

Joined: Sun May 07, 2006 5:19 am
Posts: 101


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 12:50 am 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 5:36 am 
Offline
Forum Contributor
User avatar

Joined: Sun May 07, 2006 5:19 am
Posts: 101


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 14, 2006 8:11 am 
Offline
Jedi Mod
User avatar

Joined: Tue Dec 21, 2004 6:03 pm
Posts: 5263
Location: usrlab.com


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 16, 2006 10:03 am 
Offline
Forum Contributor
User avatar

Joined: Sun May 07, 2006 5:19 am
Posts: 101
Ok so I tried my hand at anti-aliasing.

Here is the new version of the script (now Licensed too)

Syntax: [ Download ] [ Hide ]
<?php

/*

 * Title: GD Math Function Graphs

 * Desc: Plot graphs of explicit/parametric functions and tangents to them

 * Author: Verminox <verminox@gmail.com>

 * License: Creative Commons 2.5 - http://creativecommons.org/licenses/by/2.5/deed.en_GB

 * Version: 1.6

 * Compatibility: PHP 5 with GD 2.0.1 or better

 */




//Constants

define('pi',M_PI);

define('e',M_E);

define('h',0.001);



//Commonly used functions that are not pre-built

function ln($x){

        return log($x);

}



function sec($x){

        return 1/cos($x);

}



function cosec($x){

        return 1/sin($x);

}



function cot($x){

        return 1/tan($x);

}



function asec($x){

        return 1/acos($x);

}



function acosec($x){

        return 1/asin($x);

}



function acot($x){

        return 1/atan($x);

}



/* Main Graph Class */



class Graph {



        private $img;                   //The GD image resource

        public  $width,    $height;     //In Pixels

        public  $min_x,    $max_x;      //Limits of the X-axis in Units

        public  $min_y,    $max_y;      //Limits of the X-axis in Units

        public  $scale_x,  $scale_y;    //Measured in Pixels per Unit  

        public  $grid    = true;        //Whether or not to mark a unit-wise grid

        private $total_x,  $total_y;    //No. of units. Used internally only

        private $anti_aliasing;         //Amount of clarity. Int between 1-10. More clarity, more memory required.

        private $legend_y = 25;         //Offset from top of graph to mark legend                  

        private $colors = array();      //Colors alloted to the image

       

        public function __construct($min_x,$max_x,$min_y,$max_y,$scale_x,$scale_y,$anti_aliasing = 1){

                $this->min_x   = $min_x;

                $this->max_x   = $max_x;

                $this->min_y   = $min_y;

                $this->max_y   = $max_y;

                $this->scale_x = $scale_x;

                $this->scale_y = $scale_y;

                $this->anti_aliasing = (int)$anti_aliasing;

               

                //Validate

                if ( $this->min_x >= $this->max_x || $this->min_y >= $this->max_y ){

                        die("Error! Incorrect range for either X axis or Y axis");

                }

               

                //Set Variables

                $this->total_x = $this->max_x   - $this->min_x;

                $this->total_y = $this->max_y   - $this->min_y;

                $this->width   = $this->total_x * $this->scale_x * $this->anti_aliasing;

                $this->height  = $this->total_y * $this->scale_y * $this->anti_aliasing;

       

                //Create

                $this->img = @imagecreatetruecolor($this->width,$this->height) or die('Cannot Initialize new GD image stream');

               

                //Colors

                $this->colors['black']    = imagecolorallocate($this->img, 0, 0, 0);

                $this->colors['white']    = imagecolorallocate($this->img, 255, 255, 255);

                $this->colors['red']      = imagecolorallocate($this->img, 255, 0, 0);

                $this->colors['blue']     = imagecolorallocate($this->img, 0, 0, 255);

                $this->colors['orange']   = imagecolorallocate($this->img, 210, 90, 0);

                $this->colors['green']    = imagecolorallocate($this->img, 0, 128, 0);

                $this->colors['purple']   = imagecolorallocate($this->img, 128, 0, 128);

                $this->colors['grey']     = imagecolorallocate($this->img, 204, 204, 204);

               

                //Main Fill

                imagefill($this->img,0,0,$this->colors['white']);

               

                //Grid and Marking: X-axis

                for (  $unit_x = floor($this->min_x) + 1; $unit_x < $this->max_x; $unit_x++ ){

                        $pixel_x = $this->unit2pixel_x($unit_x);

                        if($this->grid){

                                imageline($this->img, $pixel_x, 0, $pixel_x, $this->height, $this->colors['grey']);

                        }

                        imagestring($this->img, 1, $pixel_x-5, 10, $unit_x, $this->colors['black']);

                        imagestring($this->img, 1, $pixel_x-5, $this->height-20, $unit_x, $this->colors['black']);

                }      

               

                //Grid and Marking: Y-axis     

                for (  $unit_y = floor($this->min_y) + 1; $unit_y < $this->max_y; $unit_y++ ){

                        $pixel_y = $this->unit2pixel_y($unit_y);

                        if($this->grid){

                                imageline($this->img, 0, $pixel_y, $this->width, $pixel_y, $this->colors['grey']);

                        }

                        imagestring($this->img, 1, 10, $pixel_y-5, $unit_y, $this->colors['black']);

                        imagestring($this->img, 1, $this->width-20, $pixel_y-5, $unit_y, $this->colors['black']);

                }

               

                //Draw Border

                imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$this->colors['black']);

               

                //X-axis

                imageline($this->img,0,$this->unit2pixel_y(0),$this->width,$this->unit2pixel_y(0),$this->colors['black']);

                //Y-axis

                imageline($this->img,$this->unit2pixel_x(0),0,$this->unit2pixel_x(0),$this->height,$this->colors['black']);

               

        }

       

        //Conversions

        private function unit2pixel_x($unit){

                $pixel = ($unit - $this->min_x) * $this->scale_x * $this->anti_aliasing;

                return $pixel;

        }

       

        private function unit2pixel_y($unit){

                $pixel = ($this->max_y - $unit) * $this->scale_y * $this->anti_aliasing;

                return $pixel;

        }

       

        private function pixel2unit_x($pixel){

                $unit = $this->min_x + ($pixel / ($this->scale_x * $this->anti_aliasing));

                return $unit;

        }

       

        private function pixel2unit_y($pixel){

                $unit = $this->max_y - ($pixel / ($this->scale_y * $this->anti_aliasing));

                return $unit;

        }

       

        //Plot the graph of a locus

        public function plot($locus){

                //Draw a colored box with the equation(s) of the locus (unless $locus->legend is false)

                if($locus->legend){

                        imagefilledrectangle($this->img,25,$this->legend_y,40,$this->legend_y+10,$this->colors[$locus->color]);

                        imagestring($this->img, 3, 45,$this->legend_y, $locus->express(), $this->colors[$locus->color]);

                        $this->legend_y += 15;

                }

               

                /*

                This is the main loop.

                We will assume a parameter $t to vary between the limits of the locus

                If the locus is parametric, it will be in the form of:

                        x = g(t);

                        y = f(t);

                If the locus is explicit, it will be in the form of:

                        x = g(t) = t;

                        y = f(t) = f(x);

                So $x can also be a variable in the equation for $y if $x==$t

                Now, for each value of $t, we will get the value for $x and $y in Units.

                Then we will convert this value into the absolute pixel value based on the

                dimensions of the graph which are done by the conversion functions defined above.

                A single point corresponding to the co-ordinates will then be plotted.

                */


               

                for($t = $locus->min; $t <= $locus->max; $t += $locus->increment){             

                        $x = @$locus->g($t);

                        $y = @$locus->f($t);

                        if ( $x === NULL || $x === false || $y === NULL || $y === false ){ continue; }

                        $pixel_x = $this->unit2pixel_x($x);

                        $pixel_y = $this->unit2pixel_y($y);

                        if ( $pixel_y < 0 || $pixel_y > $this->height || $pixel_x < 0 || $pixel_x > $this->width ){

                                continue;

                        }

                        imagesetpixel($this->img,$pixel_x,$pixel_y,$this->colors[$locus->color]);                      

                }

        }

       

        //Create the image as PNG

        public function draw($filename = NULL){

                if( $this->anti_aliasing != 1 ){

                        $img = imagecreatetruecolor( $this->width / $this->anti_aliasing , $this->height / $this->anti_aliasing ) and

                        imagecopyresampled ( $img, $this->img, 0, 0, 0, 0, $this->width / $this->anti_aliasing, $this->height / $this->anti_aliasing, $this->width, $this->height );

                } else {

                        $img = $this->img;

                }

       

                if( $filename ) {

                        $draw = imagepng($img,$filename);

                } else {

                        header("Content-type: image/png");

                        header("Pragma: No-cache");

                        $draw =  imagepng($img);

                }

                imagedestroy($img);

                return $draw;

        }

       

        //The image can be destroyed either manually...

        public function destroy(){

                return imagedestroy($this->img);

        }

       

        //...or automatically at the end of script execution. So there will never be a memory overload.

        public function __destruct(){

                return @imagedestroy($this->img);

        }

       

}



/* Main Locus Class; Both Explicit and Parametric */



class Locus {

       

        public $x = 't'; //Equation for x = g(t)

        public $y = 'x'; //Equation for y = f(t). Note: y can also be f(x) if x==t, i.e Explicit relation

        public $color = 'black'; //Key for graph::colors[]

        public $min = -10;  //Min value for t

        public $max =  10;  //Max value for t

        public $increment = 0.01; //&#948;t i.e small increment in t during the loop for graph::plot()

        public $legend = true; //Whether or not to display a legend at the top left of the graph

       

        //Regexp pattern used in self::interpret()

        const VAR_PATTERN = '/([\s\(\)\[\]\,\^\*\/\+\-\d])(x|t)([\s\(\)\[\]\,\^\*\/\+\-\d])/';

       

       

        const EXPLICIT = 't'; //Used in locus::__construct() if explicit

        //For example: $var = new locus(locus::EXPLICIT, 'sin(x)');

       

       

        //Constructor. First param can be locus::EXPLICIT if $y is a function of x.

        public function __construct($x='t',$y='0'){

                $this->x = $x;

                $this->y = $y;

        }

       

        //Change short hand terms in the equation to PHP-valid syntax

        public static function interpret($equation){

                $equation = self::pad($equation);              

               

                //Change 't' to '$t'. In case of explicit, change 'x' to '$t' as well since $x==$t.

                $equation = preg_replace(self::VAR_PATTERN,"$1\$t$3",$equation);

               

                //Shorthand exponential terms. Not for use with complex expressions. Stuff like e^x allowed.

                //For complex terms, use pow() instead

                $equation = preg_replace('/([^\s\(\,]+)\^([^\s\)\,]+)/',"pow($1,$2)",$equation);       

               

                //Change '2x' to '2*x' and '(x+1)(x+2)' into '(x+1)*(x+2)', etc.

                $equation = preg_replace('/([\d\)])([\$\(a-z])/',"$1*$2",$equation);

               

                return $equation;

        }

       

        //Add whitespace at the ends for matching with self::VAR_PATTERN

        protected static function pad($str){

                return ' ' . $str . ' ';

        }

       

        //For use in legends

        public function express(){

                return 'x = ' . $this->x . '; y = ' . $this->y . '; ';

        }      

       

        //x = g(t)

        public function g($t){

                $exp = self::interpret(self::pad($this->x));

                eval("\$value = $exp;");

                return $value;

        }

       

        //y = f(t)

        public function f($t){

                $exp = self::interpret(self::pad($this->y));           

                eval("\$value = $exp;");

                return $value;

        }

       

        //Self-explanatory

        public function is_parametric(){

                return (trim($this->x) !== 't');

        }

       

        //Alias of $graph->plot($this)

        public function plot_on(&$graph){

                $graph->plot($this);

        }

       

}



/* Class for constructing a tangent to a given locus at a given point */



class Tangent extends Locus {

       

        public function __construct(&$locus,$t){

                //Finding the derivative                                       

                $dy = $locus->f($t+h) - $locus->f($t); 

                $dx = $locus->g($t+h) - $locus->g($t);

                //m = dy/dx => Slope of tangent

                $m = ( $dy ) / ( $dx );

                //Point of contact of tangent

                $x1 = $locus->g($t);

                $y1 = $locus->f($t);

               

                /*

                Now, we have the slope of the tangent, and point of contact.

                By the slope-point form, its equation is

                        y - y1 = m(x - x1)

                        y = m(x - x1) + y1

                Note that here $m, $x and $y are passed as values instead of variables. The single 'x' part gets interpretted later on while plotting the graph to varying values of $x = $t

                */


                $this->y = "( $m * ( x - $x1) ) + $y1";

               

                $this->legend = false; //Not really needed for a tangent, but can be manually changed

        }

       

}



?>






Basically, the new thing is the last param in Graph::__construct(). It is an integer by which the scale/dimensions of the graph will be multiplied while making the image, and then the image will resampled to the desired size when Graph::draw() is called.

So the following:

Syntax: [ Download ] [ Hide ]
$graph = new Graph(-10,10,-10,10,40,40,2);


Should be a 800X800 image (20 units * 40 px/unit on both axes). However, due to the last param being '2', the image will be made as 1600X1600 and scaled at 80px/unit while plotting the graph, then resized back to 800X800 when it is drawn.


My only problem now is getting the text font size to also multiply along with the rest of the graph. I don't know how to specify text size using imagestring(). So when the image is resized back to normal the text becomes really very small. Any help?


Edit: Oh and another thing.... it seems the whole idea was useless after all. The higher I specify the multiplier, the ligher the image becomes when it is resized. In fact, it is so faint that you can see almost nothing if the multiplier is > 4. Bummer :(


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 16, 2006 5:37 pm 
Offline
Moderator
User avatar

Joined: Mon Nov 03, 2003 7:13 pm
Posts: 5978
Location: Odessa, Ukraine


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group