#!/usr/bin/perl
# helper package for gdcode Does scaling etc. 
# note that this is not used when generating gcode, only when generating jpegs. 
package scale; 
$VERSION=0.01; 
my $pi=3.1415926; 
sub new
{
	my $s={};

	$s->{ox}=$s->{oy}=0; 
	$s->{s}=1.0; 

	return bless $s;
}

sub setorigin
{
	my ($s,$x,$y)=@_; 

    $s->{ox}=$x;
	$s->{oy}=$y;

}
sub setpixelorigin
{
	my ($s,$x,$y)=@_; 

    $s->{pox}=$x;
	$s->{poy}=$y;

}


sub setscale
{
	my ($s,$scale,$xsize,$ysize)=@_; 

	

	$s->{s}=$xsize/$scale; 
	$s->{xsize}=$xsize; 
	$s->{ysize}=$ysize; 
	$s->{pox}=$xsize/2; 
	$s->{poy}=$ysize/2; 
}

sub scalexy
{
	my $s=shift(@_); 
	my (@xyus)=@_;  # unscaled xy pairs
	my @xys;        # scaled xy pairs
#	print "scalexy b4 is @xyus\n"; 
	while (@xyus)
	{
		my $x=$xyus[0]; 
		my $y=$xyus[1];
		push(@xys, (int(0.5+($x-$s->{ox})*$s->{s})+$s->{pox}),int(0.5+(($y-$s->{oy})*$s->{s})+$s->{poy})); 
		shift(@xyus); shift(@xyus); 
	}
#    print "scalexy after is @xys\n"; 
	return (@xys); 
}
sub scaled # scale a distance only, no origin offset, use for things like diameters
{
	my $s=shift(@_); 
	return map { int(0.5+$_*$s->{s}) } @_;  
}

# graphical routine. Has same interface as gcode pretty much. 
package gdcode;
use GD; 
@ISA=qw(Exporter); 
@EXPORT=qw( x y z d f r ); 
my $f="%9f "; 
my $ff="%2.1f";
sub x {'x'}
sub y {'y'} 
sub z {'z'} 
sub f {'f'} 
sub r {'r'} 
sub d {'d'}
sub new
{
	my ($self,$file,$scale,$xsize,$ysize)=@_; 
	my $g={};
	
	my $i = new GD::Image($xsize,$ysize);
	my $s=new scale; 
	$s->setscale($scale,$xsize,$ysize);
	$s->setorigin(0,0); 
	$g->{i}=$i; 
	$g->{x}=0; 
	$g->{y}=0;
	$g->{z}=0; 
	$g->{s}=$s; 
	$g->{file}=$file; 


	# allocate some colors
	$g->{col}->{white} = $i->colorAllocate(255,255,255);
    $g->{col}->{black} = $i->colorAllocate(0,0,0);       
	$g->{col}->{blue}  = $i->colorAllocate(0,0,255);
	$g->{col}->{red}   = $i->colorAllocate(255,0,0);      
   

    #$red = $i->colorAllocate(255,0,0);      
    #$blue = $i->colorAllocate(0,0,255);
	#$green=$i->colorAllocate(0,255,0); 
	#$turk=$i->colorAllocate(0,255,255); 
	#$beig=$i->colorAllocate(196,128,0);
	#$purp=$i->colorAllocate(128,0,128);

	return bless $g; 
}

# internal function. used for all circular arcs, emulates the 
# gcode arc command. 
sub arcpath
{
	my ($i,$s,$x1,$y1,$x2,$y2,$r,$col)=@_; 
   
	my $l=sqrt((($x2-$x1)**2)+(($y2-$y1)**2));            # dist between supplied points
    printf "%f %f\n",$r,$l/2;
	my $l2=sqrt(abs($r**2-($l/2)**2)); 					      # dist from center of normal to arc center 
	my $a=2*atan2($l/2,$l2);                		      # vertex angle
	$ra=0.5*($pi-$a);                                     # radial line line 1/2 angle
	my $cata=atan2($y2-$y1,$x2-$x1); 

 	my $a2=-($pi-$cata-$ra); 
	my ($cx,$cy)=($x1-$r*cos($a2),$y1-$r*sin($a2)); 
	
	$i->arc($s->scalexy($cx,$cy),$s->scaled($r*2,$r*2),($a2)*180/$pi+360,($a2+$a)*180/$pi+360,$col);
}


sub ginit
{
	my ($g)=@_; 
	
}
sub gcomment
{
   shift if (ref($_[0]) eq 'gdcode');    
   my ($c)=@_; 

   print  "*** $c \n"; 
   return; 
}
sub gmove
{
	my ($g)=shift; 
	my (@xy)=($g->{x},$g->{y}); 
	while (@_)
	{
	   $g->{$_[0]}=$_[1]  if ($_[0] =~/^[xyz]$/i);
	   shift; shift; 
	}
	push(@xy,$g->{x},$g->{y});
	
	my $col=$g->{z}>=0?$g->{col}->{red}:$g->{col}->{blue}; 
	$g->{i}->line($g->{s}->scalexy(@xy),$col);
}
sub garcccw
{
	my ($g)=shift; 
	my (@xy)=($g->{x},$g->{y}); 
	my ($r); 
	while (@_)
	{
	   $g->{$_[0]}=$_[1]  if ($_[0] =~/^[xyz]$/i); # i,j not implemented
   	   $r=$_[1]  if ($_[0] =~/^[r]$/i);
	   shift; shift; 
	}
	@xy=(@xy,$g->{x},$g->{y}); 
	my $col=$g->{z}>=0?$g->{col}->{red}:$g->{col}->{blue}; 
	arcpath($g->{i},$g->{s},@xy,$r,$col); 
}
sub garccw
{
	my ($g)=shift; 
	my (@xy)=($g->{x},$g->{y}); 
	my ($r); 
	while (@_)
	{
	   $g->{$_[0]}=$_[1]  if ($_[0] =~/^[xyz]$/i); # i,j not implemented
   	   $r=$_[1]  if ($_[0] =~/^[r]$/i);
	   shift; shift; 
	}
	@xy=($g->{x},$g->{y},@xy); 
	my $col=$g->{z}>=0?$g->{col}->{red}:$g->{col}->{blue}; 
	arcpath($g->{i},$g->{s},@xy,$r,$col); 
}
# although cutter compensation changes the path plotted by, roughly speaking
# the radius of the tool, we dont show this here, all we show 
# is the actual path plotted. These functions therefore do nothing 
sub gcompr
{
	
}
sub gcompl
{
	
}
sub gcomp0
{
	
}
# generate the output 
sub gend
{
	my ($g)=@_; 
	open(F,">".$g->{file}) or die "Cannot open file ".$g->{file}; 
	binmode F; 
    print F $g->{i}->png; 
    close F; 
}
1;

