For some reason I really enjoy coding mathematical equations. This little script will graph a sine wave, and display some info on the wave as well. Here's some of the images it produced:
I'm pretty sure these are somewhat accurate. The script was programmed in perl using the GD library. Download it here or expand the code block below if you want to check it out.
#!/usr/bin/perl -w
##
## (c) 2010 Nick Scheibenpflug
##
use strict;
use GD;
use Math::Trig;
## 1 Unit = Nπ pixels (If N = 10: aprox. 31 pixels)
my $unit = pi * 5;
## 360x100 working area. Boarders: 10 left, 10 top, 10 bottom
my $im = new GD::Image(370, 120);
## Set some colors
my ($white, $black, $red, $blue, $green, $grey);
$black = $im->colorAllocate(255,255,255);
$black = $im->colorAllocate(0,0,0);
$red = $im->colorAllocate(255,0,0);
$blue = $im->colorAllocate(0,0,255);
$green = $im->colorAllocate(0,255,0);
$grey = $im->colorAllocate(200,200,200);
## Draw the axes
$im->line( 10, 0, 10, 120, $black); # Y axis
$im->line( 0, 60, 370, 60, $black); # X axis
## Draw tick marks on X axis
## Each grey line is Nπ, where N is any integer
for( my $x = 0; $x < 20; $x++ ) {
## Use π on X axis
my $pi = pi * $x * $unit + 10; ## $x is numerical offset (2π, 3π, etc), +10 is drawing offset.
$im->line( $pi, 0, $pi, 120, $grey);
$im->line( $pi, 53, $pi, 67, $black);
## smaller line each .5π
my $pi2 = pi * ($x / 2) * $unit + 10;
$im->line( $pi2, 57, $pi2, 63, $black);
}
## Draw tick marks on the Y axis
my $u = int($unit);
for( my $y = 60; $y < 120; $y+=($u/2)) { ## Draw the bottom half
if($y % $u == 0) {
$im->line(0, $y, 370, $y, $grey) unless $y == 60;
$im->line(6, $y, 14, $y, $black);
} else {
$im->line(8, $y, 12, $y, $black);
}
}
for( my $y = 60; $y > 0; $y-=($u/2)) { ## Now the top half
if($y % $u == 0) {
$im->line(0, $y, 370, $y, $grey) unless $y == 60;
$im->line(6, $y, 14, $y, $black);
} else {
$im->line(8, $y, 12, $y, $black);
}
}
## Initialize all these, and set them to 0. Yea, I'm lazy. :3
$_ = 0 foreach (my ($cX, $cY, $max, $min, $period));
my $line = 0; ## Set to 1 to use line drawing mode, otherwise use pixel mode.
my $accuracy = 0.05;
my $first = 1;
my $t = 1; ## Time. Coefficient of X
## Main loop. Cycle through all values of X between 1 and 360 at an increment of $accuracy
for( my $x = -10; $x < 360; $x+=$accuracy ) {
my $o = 46; ## Offset.
## Y = $sine; -1 flips the wave upright for drawing
my $sine = (3*sin($t*$x+$o)) * -1;
## Use line() with a larger $accuracy, setPixel() with a smaller one.
## +10 is Y offset, +60 is X. Both for drawing adjustments.
my $X = $x * $unit + 10;
my $Y = $sine * $unit + 60;
if($line) {
## Starting point of first line
if( $first ) { $cX = $X; $cY = $Y; $first--; }
## Draw the line
$im->line( $cX, $cY, $X, $Y, $red);
} else {
$im->setPixel( $X, $Y, $red);
}
## Used for line starting points
if($line) {
## X of starting point
$cX = $X;
## Y of starting point
$cY = $Y;
}
## Find the minimum and maximum Y values
$max = $sine if $sine >= $max;
$min = $sine if $sine <= $min;
}
## Period is in radians, we want degrees
$period = ((2*pi)/$t) * (180/pi);
## Round these to nearest hundreths
$max = sprintf("%.2f", $max);
$min = sprintf("%.2f", $min);
$period = sprintf("%.2f", $period);
my $dispUnit = $unit / pi;
## Print a bunch of stuff on the image
my $font = gdSmallFont;
$im->string($font, 20, 97,"Max: $max",$blue);
$im->string($font, 20, 107, "Min: $min", $blue);
$im->string($font, 20, 2, "Period: $period\xb0", $blue);
$im->string($font, 20, 12, "Accuracy: $accuracy", $blue);
$im->string($font, 130, 2, "3sin(X+46)", $blue);
$im->string($font, 130, 12, "Unit: ${dispUnit}pi", $blue);
## Write the image file to disk
open OUT, '>sine.png';
binmode OUT;
print OUT $im->png;
close OUT;