# PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.

 It is currently Mon Sep 28, 2020 12:21 pm

 All times are UTC - 5 hours

 Page 1 of 1 [ 9 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: GD Math Function GraphsPosted: Sun Aug 13, 2006 9:31 am
 Forum Contributor

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:

<?php

/*

GD Math Function Graphs

Plot graphs and tangents of explicit and parametric relations

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 {

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){

//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

return ' ' . \$str . ' ';

}

//For use in legends

public function express(){

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

}

//x = g(t)

public function g(\$t){

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

return \$value;

}

//y = f(t)

public function f(\$t){

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:

<?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();

?>

<?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

 Post subject: Posted: Sun Aug 13, 2006 12:24 pm
 DevNet Master

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

Top

 Post subject: Posted: Sun Aug 13, 2006 12:47 pm
 Neighborhood Spidermoddy

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

Top

 Post subject: Posted: Mon Aug 14, 2006 12:30 am
 Forum Contributor

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

Top

 Post subject: Posted: Mon Aug 14, 2006 12:50 am
 Neighborhood Spidermoddy

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

Top

 Post subject: Posted: Mon Aug 14, 2006 5:36 am
 Forum Contributor

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

Top

 Post subject: Posted: Mon Aug 14, 2006 8:11 am
 Jedi Mod

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

Top

 Post subject: Posted: Wed Aug 16, 2006 10:03 am
 Forum Contributor

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)

<?php

/*

* Title: GD Math Function Graphs

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

* Author: Verminox <verminox@gmail.com>

* 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 {

\$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){

//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

return ' ' . \$str . ' ';

}

//For use in legends

public function express(){

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

}

//x = g(t)

public function g(\$t){

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

return \$value;

}

//y = f(t)

public function f(\$t){

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:

\$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

 Post subject: Posted: Wed Aug 16, 2006 5:37 pm
 Moderator

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

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 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 forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum

 Jump to:  Select a forum ------------------ General    General Discussion    Site News    PHPDN Suggestions    Tutorials Programming    PHP - Code    PHP - Security    PHP - Theory and Design    PHP - Frameworks    Javascript    Miscellaneous    Testing    Regex    Code Snippets    Coding Critique Design    HTML, CSS and other UI Design Technologies    Graphics    UI Design/Usability System    Databases    Linux    Installation and Configuration Business    The Enterprise    Job Hunt    Volunteer Work PHPDN Member Forums    PHPDN    PHPGD.com    Swift Mailer    Microsoft Open Q&A