/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program 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.

**********************************************************************/


#include	<stdlib.h>
#include	<math.h>
#include	"gbview.h"
#include	"memory_debug.h"
#include	"memory_routine.h"
#include	"xlerror.h"
#include	"equation.h"

void
inverse_affen(AFFEN2D * ret,AFFEN2D * a)
{
double m1[E_DIM][E_DIM];
double m2[E_DIM][E_DIM];
double v[E_DIM],result[E_DIM];
int i,j;
	for ( i = 0 ; i < E_DIM ; i ++ )
		for ( j = 0 ; j < E_DIM ; j ++ ) {
			if ( i == j )
				m1[i][j] = 1;
			else	m1[i][j] = 0;
		}
	for ( i = 0 ; i < 2 ; i ++ )
		for ( j = 0 ; j < 2 ; j ++ )
			m1[i][j] = a->matrix[i][j];
	v[0] = 1;
	for ( i = 1 ; i < E_DIM ; i ++ )
		v[i] = 0;
	for ( i = 0 ; i < E_DIM ; i ++ )
		for ( j = 0 ; j < E_DIM ; j ++ )
			m2[i][j] = m1[i][j];
	equation(result,m1,v);
	v[0] = 0;
	v[1] = 1;
	ret->matrix[0][0] = result[0];
	ret->matrix[1][0] = result[1];

	for ( i = 2 ; i < E_DIM ; i ++ )
		v[i] = 0;
	equation(result,m2,v);
	ret->matrix[0][1] = result[0];
	ret->matrix[1][1] = result[1];

	ret->org = mp_mul(ret->matrix,a->org);
	ret->org.x = - ret->org.x;
	ret->org.y = - ret->org.y;
}


XL_SEXP *
horizontal_affen(XLISP_ENV * e,XL_SEXP * s)
{
RESOURCE * r;
AFFEN2D a,b;
XL_SEXP * m,*v;
XL_SEXP * ret;

	r = get_resource_ptr(&ret,e,s->h.file,s->h.line);
	if ( r == 0 )
		return ret;
	m = get_el(s,1);
	v = get_el(s,2);
	if ( list2matrix(&ret,a.matrix,m,s->h.file,s->h.line,
			"horizontal-affen") < 0 )
		return ret;
	if ( list2vector(&ret,&a.org,v,s->h.file,s->h.line,
			"horizontal-affen") < 0 )
		return ret;
	if ( r->map.param_forward.type != MT_TRIANGLE ) {
		r->map.param_forward.type = MT_TRIANGLE;
		r->map.param_forward.opt.tri.tri_list = 0;
		r->map.param_forward.opt.tri.minrect.tl.x
			= r->map.param_forward.opt.tri.minrect.tl.y = 0;
		r->map.param_forward.opt.tri.minrect.br.x
			= r->map.param_forward.opt.tri.minrect.br.y = -1;
	}
	r->map.param_forward.opt.tri.sts = TS_FIX;
	r->map.param_forward.opt.tri.a = a;
	r->map.param_forward.opt.tri.resolution_rate
		= 1/puseudo_rate(a.matrix);

	inverse_affen(&b,&a);

	if ( r->map.param_reverse.type != MT_TRIANGLE ) {
		r->map.param_reverse.type = MT_TRIANGLE;
		r->map.param_reverse.opt.tri.tri_list = 0;
		r->map.param_reverse.opt.tri.minrect.tl.x
			= r->map.param_reverse.opt.tri.minrect.tl.y = 0;
		r->map.param_reverse.opt.tri.minrect.br.x
			= r->map.param_reverse.opt.tri.minrect.br.y = -1;
	}
	r->map.param_reverse.opt.tri.sts = TS_FIX;
	r->map.param_reverse.opt.tri.a = b;
	r->map.param_reverse.opt.tri.resolution_rate
		= 1/puseudo_rate(b.matrix);

	return 0;
}



