The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Geometry::AffineTransform::Test;
use base qw(Test::Class);

use Geometry::AffineTransform;

use strict;
use warnings;

use Test::More;
use List::Util qw(max min);
use Data::Dumper;

sub identity : Test(6) {
	my $self = shift;

	my $t = Geometry::AffineTransform->new();
	my @result;
	@result = $t->transform(10, 5);
	is_deeply(\@result, [10, 5], "identity transform");
	@result = $t->transform(0, 0);
	is_deeply(\@result, [0, 0], "identity transform");
	
	my $inverse = $t->clone()->invert();
	ok(ref($inverse), "clone()->invert()");
	isnt($inverse, $t, "clone()->invert() returns different instance");
	
	@result = $inverse->transform(10, 5);
	is_deeply(\@result, [10, 5], "reverse identity transform");
	@result = $inverse->transform(0, 0);
	is_deeply(\@result, [0, 0], "reverse identity transform");

}


sub inverse : Test(2) {
	my $self = shift;

	my $t = Geometry::AffineTransform->new();
	my @result;
	$t->scale(0, 1)->translate(7, 7);
	@result = $t->transform(10, 5, 20, 6);
	is_deeply(\@result, [7, 12, 7, 13], "to line");

    eval {
    	$t->invert();
    };
    
    like($@, qr/^Unable to invert this transform .zero determinant./, "exception for zero determinant");	
}


sub determinant : Test(2) {
	my $self = shift;

	my $t = Geometry::AffineTransform->new();
	my @result;
	$t->scale(10, 5);
	is($t->determinant(), 50, "determinant()");

    $t->scale(0, 1);
	is($t->determinant(), 0, "determinant()");
}



sub rotate : Test(5) {
	my $self = shift;

	my $t = Geometry::AffineTransform->new();
	is($t->rotate(180), $t);
    my $inverse = $t->clone()->invert();

	is_deeply([$t->transform(10, 5)], [-10, -5], "rotate 180");
	is_deeply([$inverse->transform(-10, -5)], [10, 5], "rotate 180");
	
	$t->rotate(90)->rotate(90);
	is_deeply([$t->transform(10, 5)], [10, 5], "rotate 360");

	$inverse = $t->clone()->invert();
	is_deeply([$inverse->transform(10, 5)], [10, 5], "rotate 360 inverse");
	
}



sub matrix_2x3 : Test(4) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	is_deeply([$t->matrix_2x3()], [1, 0, 0, 1, 0, 0]);

	is($t->set_matrix_2x3(1, 2, 3, 4, 5, 6), $t, "set_matrix_2x3");
	is_deeply([$t->matrix_2x3()], [1, 2, 3, 4, 5, 6]);
	is_deeply([$t->matrix()], [1, 2, 0, 3, 4, 0, 5, 6, 1]);
}



sub concatenate_matrix_2x3 : Test(2) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	$t->set_matrix_2x3(1, 2, 3, 4, 5, 6);
	is($t->concatenate_matrix_2x3(1, 2, 3, 4, 5, 6), $t, "concatenate_matrix_2x3()");
	is_deeply([$t->matrix_2x3()], [7, 10, 15, 22, 28, 40]);
}



sub concatenate : Test(1) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	$t->set_matrix_2x3(1, 2, 3, 4, 5, 6);
	my $t2 = Geometry::AffineTransform->new();
	$t2->set_matrix_2x3(1, 2, 3, 4, 5, 6);
	$t->concatenate($t2);
	is_deeply([$t->matrix_2x3()], [7, 10, 15, 22, 28, 40]);
}



sub translate : Test(2) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	$t->translate(5, 6);
	is_deeply([$t->transform(10, 5)], [15, 11]);
	$t->rotate(90);
	is_deeply([$t->transform(10, 5)], [-11, 15]);
}



sub scale : Test(1) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	$t->scale(3, 2);
	is_deeply([$t->transform(10, 5)], [30, 10]);
}



sub transform_multiple : Test(1) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new();
	$t->scale(3, 2);
	is_deeply([$t->transform(10, 5, 11, 6)], [30, 10, 33, 12]);
}




sub rect_dimensions {
#	my $self = shift;
	my ($x, $y, $x2, $y2) = @_;

	warn(Data::Dumper->Dump([[$x, $y, $x2, $y2]]));
	
	my $w = max($x, $x2) - min($x, $x2);
	my $h = max($y, $y2) - min($y, $y2);
	
	return ($w, $h);
}


sub clone : Test(3) {
	my $self = shift @_;
	my $t = Geometry::AffineTransform->new()->set_matrix_2x3(1, 2, 3, 4, 5, 6);
	my $t2 = $t->clone();
	is_deeply([$t2->matrix_2x3()], [1, 2, 3, 4, 5, 6]);
	$t->set_matrix_2x3(reverse 1, 2, 3, 4, 5, 6);
	is_deeply([$t->matrix_2x3()], [reverse 1, 2, 3, 4, 5, 6]);
	is_deeply([$t2->matrix_2x3()], [1, 2, 3, 4, 5, 6]);
	
}


sub matrix_multiply : Test(1) {
	my $self = shift;

# 	1 2 0
# 	3 4 0
# 	5 6 1

# 	1 2 0
# 	3 4 0
# 	5 6 1

#	1 * 1 + 2 * 3 + 0 * 5 =  7    1 * 2 + 2 * 4 + 0 * 6 = 10    1 * 0 + 2 * 0 + 0 * 1 = 0
#	3 * 1 + 4 * 3 + 0 * 5 = 15    3 * 2 + 4 * 4 + 0 * 6 = 22    3 * 0 + 4 * 0 + 0 * 1 = 0
#	5 * 1 + 6 * 3 + 1 * 5 = 28    5 * 2 + 6 * 4 + 1 * 6 = 40    5 * 0 + 6 * 0 + 1 * 1 = 1
	
	my @result = Geometry::AffineTransform->matrix_multiply([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]);
	is_deeply(\@result, [7, 10, 15, 22, 28, 40]);
#	diag(Data::Dumper->Dump([\@result]));

}


1;