#!/usr/bin/perl
use GD;
use lib "/home/dave/perl";
use colorlib;
require "../cgi-lib.pl";
ReadParse(*params);

$width = $params{width} || 500;
$height = $params{height} || 500;
$iters = $params{iters} || 100;
$n = $params{n} || 5;
$size = $params{size} || ($width/250);
$groups = $params{groups} || (3+int(rand 3));

$img = new GD::Image($width,$height,1);
#$img->fill(10,5,color(255,255,255));
$img->fill(1,1,color(0,0,0));
$pi = 3.14159265359;

@rgb = (
    { r => 223, g => 191, b => 63, },
    { r => 95, g => 31, b => 0, },
    { r => 0,   g => 0, b => 0, },
    );

circular_gradient(int($width/2),$height*2,0,\@rgb);

$hue = $params{hue} || 160; #blue
$sat = $params{sat} || 0.5; #full
$lum = $params{lum} || 0.5; #full

#$groups = 0;

for(my $i=0;$i<$groups;$i++) {
    my $xrange = $width / 6;
    my $yrange = $height / 6;
    my($x0) = $xrange + rand($width-2*$xrange);
    my($y0) = $yrange + rand(($height-2*$yrange) / 2);
    
    my $angle = int(rand(360));
    my $theta = $angle * ($pi / 180);
    my $x1 = $x0 + cos($theta) * (int (rand $xrange));
    my $y1 = $y0 + sin($theta) * (int (rand $yrange));
    
    #$img->line($x0,$y0,$x1,$y1,color(255,0,0));
    push @groupings,{
	# y = Mx + B
	M => (($y1-$y0)/($x1-$x0)),
	B => ($y0 - $x0 * (($y1-$y0)/($x1-$x0))),
	minx => $x0,
	maxx => $x1,
	dist => sqrt(($xrange+$yrange)/4) + sqrt(rand(($xrange+$yrange)*0.5)),
    };
}

foreach my $group (@groupings) {
    for(my $i=0;$i<$iters;$i++) {
	
	my($rootx) = $group->{minx} + rand($group->{maxx} - $group->{minx});
	my($rooty) = $group->{M} * $rootx + $group->{B};
	
	my $angle = int(rand(360));
	my $theta = $angle * ($pi / 180);
	my $dist = rand($group->{dist});
	$dist = $dist*$dist;
	my $x = int($rootx + cos($theta) * $dist);
	my $y = int($rooty + sin($theta) * $dist);

	#my($x) = int(rand ($width-$size));
	#my($y) = int(rand $height);

	#my($color) = get_rgb_color($x/$width);
	my($h,$s,$l);
	$h = $hue - 20 + (rand 40);
	$s = $sat - 0.05 + (rand 1)/10;
	#$l = rand 1;
	$l = (($i+1) / $iters) / 2;
	my($R,$G,$B) = colorlib::hsl_to_rgb($h,$s,$l);
	my($cidx) = $img->getPixel($x,$y);
	my($R0,$G0,$B0) = $img->rgb($cidx);

	#my $R1 = sqrt(($R**2 + $R0**2) / 2);
	#my $G1 = sqrt(($G**2 + $G0**2) / 2);
	#my $B1 = sqrt(($B**2 + $B0**2) / 2);

	my $R1 = ($R + $R0) / 2;
	my $G1 = ($G + $G0) / 2;
	my $B1 = ($B + $B0) / 2;

	my $color = color($R1,$G1,$B1);
	#draw_ngon($x,$y,$size,$n,color(0,0,255));
	draw_ngon($x,$y,$size,$n,$color);
    }
}

draw_grid();

print "Content-Type: image/png\n\n";
print $img->png;

sub draw_grid {
    $gcolor = color(0,127,255);

    # Draw to points on top width in normal increments until we get to about 30 degrees?
    # Lowest angle in some quick tests is around 50 degrees, 30 should be fine.
    my $meet_y = (1 + rand(1)) * $width;
    my $meet_x = $width*(4.5/10) + rand($width/10);
    my $top_left = $meet_y * sqrt(3);

    my $top_left_x = $meet_x - $top_left;

    my $top_right_x = $meet_x + $top_left;
    my $step = $width / (5.5 + rand(3.75));
    
    $img->setThickness($width*0.0062);

    for(my $tx=$top_left_x;$tx<=$top_right_x;$tx+=$step) {
	#bottom intercept point
	my $bix = ($height*$meet_x - $height*$tx + $meet_y*$tx - 0*$meet_x)/($meet_y - 0);
	if($bix > 0 && $bix < $width) {
	    # Line will appear on the image.
	    my($M) = ($meet_y) / ($meet_x - $tx);
	    my($B) = $meet_y - $M*$meet_x;
	    my $biy = $height;
	    my($tix,$tiy) = ((-1*$B)/$M,0);
	    if($tix < 0) {
		# Line connects to left side rather than the top
		$tix = 0;
		$tiy = $B;
	    } elsif($tix >= $width) {
		# Line connects to right side rather than the top
		$tix = $width-1;
		$tiy = $M*$tix + $B;
	    }
	    $img->line(int($bix),int($biy),int($tix),int($tiy),$gcolor);
	}
    }

    #Horizontal lines
    #my($step_mod) = ($step - 5.5)*(88/3.75); # If we have a bigger step, we should have bigger spacing

    #my($spacing) = (0.141 + rand(88)/1000) * $width;
    my($spacing) = (($step*88)-(88*$width)/(3.75+5.5))/(1000*((1/5.5-1/(3.75+5.5))))+$width*0.141;
    my($bary) = $spacing * rand(1);
    for(my $i=0; $i<10; $i++) {
	$img->line(0,$bary,$width-1,$bary,$gcolor);
	$bary += $spacing;
	$spacing *= 0.875;
    }

    $img->setThickness(1);
}

sub draw_ngon {
    my($x0,$y0,$size,$sides,$color) = @_;
    my($step) = 360/$sides;
    my(@points,@fillpts) = ();
    my($angle) = 0;
    for(my $i=0;$i<=$sides;$i++) {
	my $theta = $angle * ($pi / 180);
	my $x = int($x0 - $size*sin($theta));
	my $y = int($y0 - $size*cos($theta));
	push @points,{ x => $x, y => $y };

	$x = int($x0 - ($size-2)*sin($theta));
	$y = int($y0 - ($size-2)*cos($theta));
	push @fillpts,{ x => $x, y => $y };

	$angle+=$step;
    }
    push @points,{ x => $points[0]{x}, y => $points[0]{y} };
    for(my $i=1;$i<@points;$i++) {
	$img->line($points[$i-1]{x},$points[$i-1]{y},$points[$i]{x},$points[$i]{y},$color);
    }
    $img->fill($x0,$y0,$color);
    foreach my $point (@fillpts) {
	$img->fill($point->{x},$point->{y},$color);
    }
    #$img->setAntiAliased($color);
    #for(my $i=1;$i<@points;$i++) {
	#$img->line($points[$i-1]{x},$points[$i-1]{y},$points[$i]{x},$points[$i]{y},gdAntiAliased);
    #}

}

sub circular_gradient {
    my($cx,$cy,$ty,$rgb) = @_;
    
    for(my $r = ($cy-$ty); ($cy-$r) <= $height; $r--) {
	#$img->arc(500,500,200,200,180,360,color(255,0,0));
	my($min,$max) = ($cy-$height,$cy-$ty);
	my($mid) = $min + ($max-$min)*(1/3);
	
	print STDERR "R: $r Min: $cy-$ty=$min Max: $cy-$height=$max Mid: $mid\n";

	my($red) = get_curve_value($min,$mid,$max,$r,$rgb->[0]{r},$rgb->[1]{r},$rgb->[2]{r});
	my($green) = get_curve_value($min,$mid,$max,$r,$rgb->[0]{g},$rgb->[1]{g},$rgb->[2]{g});
	my($blue) = get_curve_value($min,$mid,$max,$r,$rgb->[0]{b},$rgb->[1]{b},$rgb->[2]{b});
	
	#my($red) = get_curve_value($cy-$r,($cy+$ty-$r)/2,$ty,$r,$rgb->[0]{r},$rgb->[1]{r},$rgb->[2]{r});
	#my($green) = get_curve_value($cy-$r,($cy+$ty-$r)/2,$ty,$r,$rgb->[0]{g},$rgb->[1]{g},$rgb->[2]{g});
	#my($blue) = get_curve_value($cy-$r,($cy+$ty-$r)/2,$ty,$r,$rgb->[0]{b},$rgb->[1]{b},$rgb->[2]{b});
	#$img->arc($cx,$cy,$r*2,$r*2,180,360,color($red,$green,$blue));
	$img->arc($cx,$cy,$r*2,$r*2,180,360,color($red,$green,$blue));
	$img->fill($cx,$cy-$r+1,color($red,$green,$blue));
    }
}

sub get_rgb_color {
    my($value) = @_;
    my($r,$g,$b) = (0,0,0);
    $r = get_curve_value(0,0.5,1,$value,$rgb[0]{r},$rgb[1]{r},$rgb[2]{r});
    #print STDERR "For $value, r = $r\n";
    $g = get_curve_value(0,0.5,1,$value,$rgb[0]{g},$rgb[1]{g},$rgb[2]{g});
    $b = get_curve_value(0,0.5,1,$value,$rgb[0]{b},$rgb[1]{b},$rgb[2]{b});
    return(color($r,$g,$b));
}

sub get_curve_value {
    my($min,$mid,$max,$val,$lowv,$midv,$highv) = @_;
    my($ret) =  ((($val-$mid)*($val-$max))/(($min-$mid)*($min-$max)))*$lowv;
    $ret += ((($val-$min)*($val-$max))/(($mid-$min)*($mid-$max)))*$midv;
    $ret += ((($val-$min)*($val-$mid))/(($max-$min)*($max-$mid)))*$highv;
    $ret = int $ret;
    $ret = $lowv if($val < $min);
    $ret = $highv if($val > $max);
    $ret = 255 if($ret > 255);
    $ret = 0 if ($ret < 0);
    return $ret;
}

sub get_curve_value2 {
    my($x0,$x1,$x2,$x,$y0,$y1,$y2) = @_;
    my($A,$B,$C);
    if($x < $x0) { return $y0; }
    if($x > $x2) { return $y2; }
    $A = ($y2*$x1 - $y2*$x0 + $x2*$y1 - $x2*$y0) / ($x2*$x2*$x1 - $x2*$x2*$x0 + $x1*$x1*$x2 - $x0*$x0*$x2);
    $B = ($y1 - $A*$x1*$x1 - $y0 + $A*$x0*$x0) / ($x1 - $x0);
    $C = $y0 - $A*$x0*$x0 - $B*$x0;
    my $y = $A*$x*$x + $B*$x + $C;
    if($y > 255) { return 255; }
    elsif($y < 0) { return 0; }
    else { return int($y); }
}

sub color {
    my($r,$g,$b) = @_;
    if(!defined($pal{"$r\_$g\_$b"})) {
        $pal{"$r\_$g\_$b"} = $img->colorAllocate($r,$g,$b);
    }
    return $pal{"$r\_$g\_$b"};
}
