/* Copyright 2003  Alexander V. Diemand

    This file is part of MolTalk.

    MolTalk is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    MolTalk is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MolTalk; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

/* vim: set filetype=objc: */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "Matrix53.oh"
#include "Matrix44.oh"
#include "Coordinates.oh"


@implementation Matrix53


-(id)init	//@nodoc
{
	[super init];
	[super setRows:5 cols:3];
	[self atRow: 0 col: 0 value: 1.0];
	[self atRow: 1 col: 1 value: 1.0];
	[self atRow: 2 col: 2 value: 1.0];
	return self;
}

-(void)dealloc	//@nodoc
{
	[super dealloc];
}


/*
 *   returns the matrix for an inverse transformation
 */
-(Matrix53*)invert
{
	double t;
	t = [self atRow: 0 col: 1];
	[self atRow: 0 col: 1 value: [self atRow: 1 col: 0]];
	[self atRow: 1 col: 0 value: t];
	t = [self atRow: 0 col: 2];
	[self atRow: 0 col: 2 value: [self atRow: 2 col: 0]];
	[self atRow: 2 col: 0 value: t];
	t = [self atRow: 1 col: 2];
	[self atRow: 1 col: 2 value: [self atRow: 2 col: 1]];
	[self atRow: 2 col: 1 value: t];
	t = [self atRow: 3 col: 0];
	[self atRow: 3 col: 0 value: [self atRow: 4 col:0]];
	[self atRow: 4 col: 0 value: t];
	t = [self atRow: 3 col: 1];
	[self atRow: 3 col: 1 value: [self atRow: 4 col:1]];
	[self atRow: 4 col: 1 value: t];
	t = [self atRow: 3 col: 2];
	[self atRow: 3 col: 2 value: [self atRow: 4 col:2]];
	[self atRow: 4 col: 2 value: t];
	return self;
}


/*
 *   return rotation matrice
 */
-(Matrix44*)getRotation
{
	Matrix44 *res = [Matrix44 matrixIdentity];
	[res atRow: 0 col: 0 value: [self atRow: 0 col: 0]];
	[res atRow: 0 col: 1 value: [self atRow: 0 col: 1]];
	[res atRow: 0 col: 2 value: [self atRow: 0 col: 2]];
	[res atRow: 1 col: 0 value: [self atRow: 1 col: 0]];
	[res atRow: 1 col: 1 value: [self atRow: 1 col: 1]];
	[res atRow: 1 col: 2 value: [self atRow: 1 col: 2]];
	[res atRow: 2 col: 0 value: [self atRow: 2 col: 0]];
	[res atRow: 2 col: 1 value: [self atRow: 2 col: 1]];
	[res atRow: 2 col: 2 value: [self atRow: 2 col: 2]];
	
	return res;
}


/*
 *   return translation matrice
 */
-(Matrix44*)getTranslation
{
	Matrix44 *res = [Matrix44 matrixIdentity];
	[res atRow: 3 col: 0 value: [self atRow: 4 col: 0]];
	[res atRow: 3 col: 1 value: [self atRow: 4 col: 1]];
	[res atRow: 3 col: 2 value: [self atRow: 4 col: 2]];
	return res;
}


/*
 *   return reset-to-origin vector
 */
-(Coordinates*)getOrigin
{
	Coordinates *res = [Coordinates new];
	[res atDim: 0 value: [self atRow: 3 col: 0]];
	[res atDim: 1 value: [self atRow: 3 col: 1]];
	[res atDim: 2 value: [self atRow: 3 col: 2]];
	[res atDim: 3 value: 0.0];
	return AUTORELEASE(res);
}

/*
 *   read and initializes a matrix from a string
 */
+(Matrix53*)matrixFromString:(NSString*)str
{
/* a matrix might look like this: 
 [ [-0.506316,0.559328,0.656350] [-0.607832,-0.771377,0.188463] [0.611706,-0.303529,0.730538] [62.893028,10.183025,-0.708629] [19.371693,40.109528,10.753658] ]
*/
	Matrix53 *res = [Matrix53 new];
	NSScanner *sc = [NSScanner scannerWithString: str];
	[sc  setCharactersToBeSkipped: [NSCharacterSet characterSetWithCharactersInString: @"[] 	,"]];
	double val;
	int irow,icol;
	for (irow=0; irow<5; irow++)
	{
		for (icol=0; icol<3; icol++)
		{
			if (![sc scanDouble: &val])
			{
				NSLog(@"scan failed.");
				return nil;
			}
			[res atRow: irow col: icol value: val];
		} /* icol */
	} /* irow */
	return AUTORELEASE(res);
}


/*
 *   create identity matrix
 */
+(id)matrixIdentity
{
	Matrix53 *res = [Matrix53 new];
	return AUTORELEASE(res);
}


@end

