<?php
set_time_limit(120);		// geloof me, hij vreet tijd!

define('IMAGES', 3);		// x bij x plaatjes; bijv. 3 levert 3 x 3 = 9 
							// plaatjes op
							
define('WIDTH', 300);		// breedte van een individueel plaatje

define('HEIGHT', 300);		// hoogte van een individueel plaatje

define('FREQUENTIE', 0.1);	// frequentie, hoe lager hoe mooier de golven
							// zichtbaar zijn. ong: 1 / aantal pixels per golf

define('BRON_VERSCHIL_STAP', 2);	// stapgrote waarmee de bronnen uit elkaar
									// bewegen

/**
 * Golffuncties
 */

function standaardGolf($t)
{
	return sin(2 * pi() * FREQUENTIE * $t);
}

function omgekeerdeGolf($t)
{
	return standaardGolf($t) * -1;
}


/**
 * Definitie van een positie. Een positie kan zijn afstand ten opzichte van
 * een andere positie uitrekenen. Handig voor $t voor de golffuncties.
 */

class Positie {
	public
		$x,
		$y;
	
	public function __construct($x, $y)
	{
		$this->x = $x;
		$this->y = $y;
	}
	
	public function afstand(Positie $ander)
	{
		return sqrt(
			pow(max($this->x, $ander->x) - min($this->x, $ander->x), 2)
		+	pow(max($this->y, $ander->y) - min($this->y, $ander->y), 2)
		);
	}
}


/**
 * Een bron is een golffunctie op een beplaald punt. Met behulp van de functie
 * en de afstand tussen de positie van de bron en de positie van de pixel die
 * wordt uitgerekend wordt de fase bepaald, welke verantwoordelijk is voor
 * de grijze tint.
 */

class Bron {
	public
		$positie,
		$functie;
	
	public function __construct(Positie $positie, $functie = 'standaardGolf')
	{
		$this->positie = $positie;
		$this->functie = $functie;
	}
	
	public function fase($t)
	{
		$f = $this->functie;
		return $f($t);
	}
}

$x = IMAGES * WIDTH;
$y = IMAGES * HEIGHT;

$spectrum = array();
$img = imagecreatetruecolor($x, $y);
$positie = new Positie(0, 0);
$offset  = new Positie(0, 0);


// Spectrum met kleuren maken. Naja, kleuren, eigenlijk 256 grijswaarden
for($i = 0; $i < 256; $i++) {
	$spectrum[$i] = imagecolorallocate($img, $i, $i, $i);
}

$i = 0;

// lussen voor de plaatjes
for($offset->y = 0; $offset->y < $y; $offset->y += HEIGHT) {
	for($offset->x = 0; $offset->x < $x; $offset->x += WIDTH) {
		// positie bronnen bepalen, staat hier omdat $i variabel is.
		$bronnen = array(
			new Bron(
				new Positie((WIDTH / 2) - $i, 50), 
				'standaardGolf'),
			new Bron(
				new Positie((WIDTH / 2) + $i, 50),
				'omgekeerdeGolf')
		);
	
		$i += BRON_VERSCHIL_STAP;
		
		// lussen voor de pixels van het plaatje
		for($positie->x = 0; $positie->x < WIDTH; $positie->x++) {
			for($positie->y = 0; $positie->y < HEIGHT; $positie->y++) {
				$intensiteit = 0;
		
				// bereken voor iedere bron de intensiteit op dit punt
				foreach($bronnen as $bron) {
					$intensiteit += $bron->fase($positie->afstand($bron->positie));
				}
			
				$intensiteit = $intensiteit / count($bronnen);
				
				// kleur de pixel op dit punt op basis van de intensiteit met 
				// één van de kleuren uit het spectrum.
				imagesetpixel(
					$img, 
					$positie->x + $offset->x, 
					$positie->y + $offset->y, 
					$spectrum[round((($intensiteit + 1) / 2) * 255, 0)]);
			}
		}
	}
}

// Plaatje omzetten naar iets gangbaars en opsturen naar de browser
header('Content-Type: image/png');
imagepng($img);
?>