Keeping it Small and Simple

2007.05.19

Plotting trigonometrical functions in PHP

Filed under: Graphics Programming, Mathematics, PHP Programming — Lorenzo E. Danielsson @ 02:48

If you’ve ever tried software applications like MRTG or Zabbix you will have seen that these programs are able to generate graphs that are displayed on a web page. If you wonder how it’s done, I hope that this short tutorial will give you an idea.

I’m going to use PHP for this example, but it wouldn’t be difficult to adapt to mod_perl, mod_ruby or possibly mod_pascal (is there such a thing??). To begin with we will need a web server (I’m using Apache2 with PHP support. If you are using Debian or one of its derivates, aptitude install libapache2-mod-php5 should do the trick (you could also use libapache2-mod-php4 if you prefer). You will also need the PHP GD (www.libgd.org library for dynamically creating images. You get that with aptitude install php5-gd.

The GD library allows to create an image, use various functions to draw on the image and finally stream the image to the client (web browser). GD itself is written in C, but there are bindings for several languages available. There are also various utility libraries available that build on top of GD, that make it easier to use GD for specific purposes, but it’s always a good idea to understand how things work at a lower level, so in this tutorial I will look at GD itself.

The procedure is quite simple:

  1. Create an image (either a new blank image or load an existing image)
  2. Perform drawing operations on the image
  3. Stream the image data to the client

In this example, I’m going to plot the two trigonometrical functions sine and cosine. We will create two files. I called the first on trigplot.php (you can call it whatever you want), and it looks like this:

<?php

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

function draw_axes($image, $width, $height, $color) {
    $xaxis = $height / 2;
    $yaxis = $width / 2;

    imageline($image, $yaxis, 0, $yaxis, $height-1, $color);
    imageline($image, 0, $xaxis, $width-1, $xaxis, $color);
}

function plot_sin($image, $height, $color) {
    for ($x = 0; $x < 360; ++$x) {
        $amplitude = $height/2 - 10;
        $y = $height/2 + $amplitude * sin(deg2rad($x-180));
        imagesetpixel($image, $x, $y, $color);
    }
}

function plot_cos($image, $height, $color) {
    for ($x = 0; $x < 360; ++$x) {
        $amplitude = $height/2 - 10;
        $y = $height/2 + $amplitude * cos(deg2rad($x-180));
        imagesetpixel($image, $x, $y, $color);
    }
}

$width = 360;
$height = 200;
$image = imagecreate($width, $height) or die("Failed to create stream");
$bgcolor = imagecolorallocate($image, 255, 255, 255);
$axiscolor = imagecolorallocate($image, 0, 0, 0);
$curvecolor1 = imagecolorallocate($image, 0, 0, 255);
$curvecolor2 = imagecolorallocate($image, 0, 255, 0);

draw_axes($image, $width, $height, $axiscolor);
plot_sin($image, $height, $curvecolor1);
plot_cos($image, $height, $curvecolor2);
imagepng($image);
imagedestroy($image);

?>

(Sorry for the lack of line numbering, Vim gave me errors when I tried to run :TOhtml with line numbering enabled.)

Notice the header call. This is important. We are sending image data to the web browser, so we must notify it of the content type, so that it will now what to do with the incoming data. The rest should be fairly straightforward I hope (make sure you have you PHP documentation open so that you can read up on the functions that are used). Of course you don’t have separate code this short into functions, but I did it just to show that this is a PHP file like any other and that you can use normal PHP constructs in it.

You could now upload this file to a location where you web server is able to serve it, and you should see a very simple graph containing to curves in different colors. As far as the web browser is concerned, this is an image it is displaying, similar to the way the browser will display any other image. The browser is not at all concerned with the fact that this image is, in fact, dynamically created.

If, instead of seeing an image in your browser, you get something about the image not being displayed because it contains errors then skip down to the section called A little note on debugging.

But how about if you would want to include the graph in an existing web page? That is not a problem at all. Here is a sample, you could call it index.html if you want.

<html>
<head>
<title>Trigonometry plotter</title>
</head>

<body>
<center><b>Trigonometry Functions</b></center>
<img src="trigplot.php">
</body>
</html>

Notice that I am using a normal HTML IMG tag, and pay attention to the SRC attribute. That is really all there is to it (I’m not calling the blog Keeping it Small and Simple for nothing).

A little note on debugging

If a syntax error creeps into your image generation code, then you will just get a blank image if you browse index.html. If you browse trigplot.php, on the other hand, you will get a message that the image cannot be displayed because it contains errors. To get some useful information about the error, browse trigplot.php and get your browser to view the source. It will contain error messages from PHP, along with line numbers. With that your debugging almost becomes trivial.

You will not see any error messages if you try to view the source of index.html. You must browse something like http://localhost/phpsamples/trigplot/trigplot.php to be able to see the error messages that PHP sends you.

Ideas for exercises

For those who feel so inclined I’ve added a few ideas for exercises based on my sample. You can try them if you don’t have anything better to do. Feel free to post your solutions as comments. (No, I’m not going to give you a degree in computer science. 😀 )

  1. Add a border around the graph.
  2. Add labels to the curves (something like y = sin(x) and y = cos(x)). Make sure these get well positioned.
  3. The axes are currently just straight lines. Make them look more like the ones you would find in your average school math book. Add arrows, labels etc.
  4. All drawing in the original is done by GD. Use a drawing program to create an image that contains labeled axes and has a border around it. In your PHP code, use the imagecreatefrompng() function to load the image and then perform you function plotting on it. Make sure you get your positioning right.
  5. Add y = tan(x) to the graph. What special condition do you need to take into consideration when plotting this function?
  6. Add a grid. Choose a light gray color so that it doesn’t dominate the graph.
  7. Create a form that asks the user for information like amplitude, start angle, end angle, wavelength etc, and uses this information to plot the functions.
  8. In the plot functions, highlight the maximum and minimum points of the sine and cosine functions.
  9. Write a Perl program that uses an Inline Asm section to dynamically generate PHP code that dynamically creates graphs of trigonometric functions. 😉

These are just a few examples that I can think of.

Addendum

Spot the error in the code? Hint: think Cartesian vs. screen coordinates. You can fix that by changing $y = $height/2 + ... to $y = $height/2 - ... in the two functions plot_sin and plot_cos.


Update 2007.05.23: Noticed an error in the code.

Advertisements

1 Comment »

  1. Cool stuff. I’m going to try the exercise when I get some free time.Will post back my code.

    Comment by eyedol — 2007.05.19 @ 05:27


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: