# $Id: Projection.pm 2010-08-31 aj3 $

package Axonometrie::Projection;

use strict;
use warnings;
use 5.007;

our $VERSION = 0.01;

use Carp;
use Data::Dumper;



sub new {
	my ($class, $options) = @_;
	
	my $self = {};
	bless $self, $class;
	
	$self->_parseOptions($options);
	
	return $self;
}



sub _parseOptions {
	my ($self, $options) = @_;
	
	# :TODO: actually parse the options
	$self->{options} = $options;
	
	$self->{options}->{scale} ||= 1;
	$self->{options}->{ratio} ||= '1:1:1';
	my ($scaleX, $scaleY, $scaleZ) = split m/[\/: ,]/, $self->{options}->{ratio};
	$self->{options}->{scaleX} ||= $scaleX * $self->{options}->{scale};
	$self->{options}->{scaleY} ||= $scaleY * $self->{options}->{scale};
	$self->{options}->{scaleZ} ||= $scaleZ * $self->{options}->{scale};
}



sub project {
	my ($self, $model) = @_;
	
	if ( ! ref $model || ref $model ne 'Axonometrie::Model' ) {
		croak('Required model attribute missing');
	}
	
	my @elements = ();
	
	my $modelObjects = $model->{objects};
	foreach my $object (@$modelObjects) {
		my @point1Unprojected = ($object->{x1}, $object->{y1}, $object->{z1});
		my @point2Unprojected = ($object->{x2}, $object->{y2}, $object->{z2});
		my $point1Projected = $self->_projectPoint(@point1Unprojected);
		my $point2Projected = $self->_projectPoint(@point2Unprojected);
		my $element = { a => $point1Projected, b => $point2Projected, class => $object->{class} };
		push @elements, $element;
	}
	
	$self->{elements} = \@elements;
}



sub _projectPoint {
	my ($self, $x, $y, $z) = @_;
	
	my $scaleX = $self->{options}->{scaleX};
	my $scaleY = $self->{options}->{scaleY};
	my $scaleZ = $self->{options}->{scaleZ};
	my $alpha = $self->{options}->{alpha};
	my $beta = $self->{options}->{beta};
	
	my $projectedX = $scaleY * $y * cos($beta) - $scaleX * $x * cos($alpha);
	my $projectedY = $scaleY * $y * sin($beta) + $scaleX * $x * sin($alpha) - $scaleZ * $z;
	
	return { x => $projectedX, y => $projectedY };
}



sub elements {
	my ($self) = @_;
	
	return $self->{elements};
}



1;
