#==========================================================================
#			   Copyright (c) 1995-1998 Martien Verbruggen
#			   Copyright (c) 2000 Alan Jackson
#		Based on the pie.pm module by Martien Verbruggen
#--------------------------------------------------------------------------
#
#	Name:
#		GD::Graph::rose.pm
#
#
#==========================================================================

package GD::Graph::rose;

$GD::Graph::rose::VERSION = '$Revision: 1.00 $' =~ /\s([\d.]+)/;

use strict;

use constant PI => 4 * atan2(1,1);

use GD;
use GD::Graph;
use GD::Graph::utils qw(:all);
use GD::Graph::colour qw(:colours :lists);
use GD::Text::Align;
use Carp;

@GD::Graph::rose::ISA = qw( GD::Graph );

my $ANGLE_OFFSET = -90;

my %Defaults = (
 
	# The angle at which to start the first data set
	# 0 is at the front/bottom
	start_angle => 0,

	# Angle below which a label on a rose slice is suppressed.
	suppress_angle => 0,	# CONTRIB idea ryan <xomina@bitstream.net>

	# and some public attributes without defaults
	label		=> undef,

	# This misnamed attribute is used for rose marker colours
	axislabelclr => 'black',
);

# PRIVATE
sub _has_default { 
	my $self = shift;
	my $attr = shift || return;
	exists $Defaults{$attr} || $self->SUPER::_has_default($attr);
}

sub initialise
{
	my $self = shift;
	$self->SUPER::initialise();
	while (my($key, $val) = each %Defaults)
		{ $self->{$key} = $val }
	$self->set_value_font(gdTinyFont);
	$self->set_label_font(gdSmallFont);
}

# PUBLIC methods, documented in pod
sub plot
{
	my $self = shift;
	my $data = shift;


	$self->check_data($data) 		or return;
	$self->init_graph() 			or return;
	$self->setup_text()				or return;
	$self->setup_coords() 			or return;
	$self->draw_text()				or return;
	$self->draw_data()				or return;

	return $self->{graph};
}

sub set_label_font # (fontname)
{
	my $self = shift;
	$self->_set_font('gdta_label', @_) or return;
	$self->{gdta_label}->set_align('bottom', 'center');
}

sub set_value_font # (fontname)
{
	my $self = shift;
	$self->_set_font('gdta_value', @_) or return;
	$self->{gdta_value}->set_align('center', 'center');
}

# Inherit defaults() from GD::Graph

# inherit checkdata from GD::Graph

# Setup the coordinate system and colours, calculate the
# relative axis coordinates in respect to the canvas size.

sub setup_coords()
{
	my $self = shift;

	my $tfh = $self->{title} ? $self->{gdta_title}->get('height') : 0;
	my $lfh = $self->{label} ? $self->{gdta_label}->get('height') : 0;

	# Calculate the bounding box for the rose, and
	# some width, height, and centre parameters
	$self->{bottom} = 
		$self->{height} - $self->{b_margin} -
		( $lfh ? $lfh + $self->{text_space} : 0 );
	$self->{top} = 
		$self->{t_margin} + ( $tfh ? $tfh + $self->{text_space} : 0 );

	return $self->_set_error('Vertical size too small') 
		if $self->{bottom} - $self->{top} <= 0;

	$self->{left} = $self->{l_margin};
	$self->{right} = $self->{width} - $self->{r_margin};

	return $self->_set_error('Horizontal size too small')
		if $self->{right} - $self->{left} <= 0;

	$self->{w} = $self->{right}  - $self->{left};
	$self->{h} = $self->{bottom} - $self->{top};

	$self->{xc} = ($self->{right}  + $self->{left})/2; 
	$self->{yc} = ($self->{bottom} + $self->{top})/2;


	return $self;
}

# inherit open_graph from GD::Graph

# Setup the parameters for the text elements
sub setup_text
{
	my $self = shift;

	if ( $self->{title} ) 
	{
		#print "'$s->{title}' at ($s->{xc},$s->{t_margin})\n";
		$self->{gdta_title}->set(colour => $self->{tci});
		$self->{gdta_title}->set_text($self->{title});
	}

	if ( $self->{label} ) 
	{
		$self->{gdta_label}->set(colour => $self->{lci});
		$self->{gdta_label}->set_text($self->{label});
	}

	$self->{gdta_value}->set(colour => $self->{alci});

	return $self;
}

# Put the text on the canvas.
sub draw_text
{
	my $self = shift;

	$self->{gdta_title}->draw($self->{xc}, $self->{t_margin}) 
		if $self->{title}; 
	$self->{gdta_label}->draw($self->{xc}, $self->{height} - $self->{b_margin})
		if $self->{label};
	
	return $self;
}

# Draw the data petals

sub draw_data
{
	my $self = shift;

	for (my $j=1;$j<=$#{$self->{_data}};$j++) {
		my $total = 0; my $max = 0;
		my @values = $self->{_data}->y_values($j);	# for now, only one rose..
		for (@values)
		{	
			$total += $_ ;
			$max = $max > $_ ? $max : $_;
		}

		return $self->_set_error("Rose data total is <= 0") 
			unless $total > 0;

		my $factor = 0.5*($self->{bottom} - $self->{top})/$max; # scaling factor
		my $ac = $self->{acci};			# Accent colour
		my $pb = 0; # start angle
		# Set the data colour
		my $dc = $self->set_clr_uniq($self->pick_data_clr($j));

		for (my $i = 0; $i < @values; $i++)
		{

			# Set the angles of the rose slice
			# Angle 0 faces up, positive angles are clockwise 
			# from there.
			#          0
			#         ---
			#        / | \
			#        |    |
			#        \   /
			#         ---
			my $pa = $pb;
			$pb += 360/@values;

			# Calculate the end points of the lines at the boundaries of
			# the rose petal
			my ($xe, $ye) = cartesian(
					$values[$i]*$factor, $pa, 
					$self->{xc}, $self->{yc}, $self->{h}/$self->{w}
				);

			$self->{graph}->line($self->{xc}, $self->{yc}, $xe, $ye, $ac);

			my ($xf, $yf) = cartesian(
					$values[$i]*$factor, $pb, 
					$self->{xc}, $self->{yc}, $self->{h}/$self->{w}
				);

			$self->{graph}->line($xe, $ye, $xf, $yf, $ac);
			$self->{graph}->line($self->{xc}, $self->{yc}, $xf, $yf, $ac);

			# Make an estimate of a point in the middle of the rose petal
			# And fill it
			($xe, $ye) = cartesian(
					$values[$i]*$factor/2, ($pa+$pb)/2,
					$self->{xc}, $self->{yc}, $self->{h}/$self->{w}
				);

			$self->{graph}->fillToBorder($xe, $ye, $ac, $dc);

			# Horrible kludge. If the top petal is longer than the petal
			# underneath, the fill will be incomplete. So pick a point just
			# inside the far extent of the petal and fill.
			($xe, $ye) = cartesian(
					$values[$i]*$factor-2, ($pa+$pb)/2,
					$self->{xc}, $self->{yc}, $self->{h}/$self->{w}
				);
			$self->{graph}->fillToBorder($xe, $ye, $ac, $dc);



		}
	}

	return $self;

} #GD::Graph::rose::draw_data


# return x, y coordinates from input
# radius, angle, center x and y and a scaling factor (height/width)
#
# $ANGLE_OFFSET is used to define where 0 is meant to be
sub cartesian
{
	my ($r, $phi, $xi, $yi, $cr) = @_; 

	return (
		$xi + $r * cos(PI * ($phi + $ANGLE_OFFSET)/180), 
		$yi + $cr * $r * sin(PI * ($phi + $ANGLE_OFFSET)/180)
	)
}

"Just another true value";
