/**********************************************************************
 
	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	"machine/u_math.h"
#include	"gbgraph.h"
#include	"win_flame.h"
#include	"memory_debug.h"
#include	"viewindex.h"

void ov_default();

extern GBVIEW_ENV env;



int
new_rotate_and_center(
	GB_POINT from,
	GB_POINT to)
{
MATRIX3D rm;
double radius;
GB_POINT3D pt,pt_old;
GB_POINT center;
MATRIX3D l_rev,p_rev,r_rev;
MATRIX3D lambda,phi,cita;
double center_lambda,center_phi;
int er;
REAL1 new_rotate;
GB_POINT new_center;
RESOURCE * r;
	r = env.flame_base->draw;
	radius = conv_unit(&er,
			r->h.cu.uenv,
			env.flame_base_resolution,
			reso_c_unit(&r->h.cu),
			l_string(std_cm,"dot/rad"));

	from.x -= env.win_width/2;
	from.y -= env.win_height/2;
	to.x -= env.win_width/2;
	to.y -= env.win_height/2;

	if ( get_gmatrix(rm,from,to,radius) < 0 )
		return -1;

	center_lambda = conv_unit(&er,
			r->h.cu.uenv,
			env.flame_base_center.x,
			r->h.cu.unit,
			l_string(std_cm,"rad"));
	center_phi = conv_unit(&er,
			r->h.cu.uenv,
			env.flame_base_center.y,
			r->h.cu.unit,
			l_string(std_cm,"rad"));

	get_round_matrix3d_lambda(lambda,center_lambda);
	get_round_matrix3d_phi(phi,center_phi);
	get_round_matrix3d_cita(cita,env.flame_base_rotate);
	pt.x = pt.y = 0;
	pt.z = 1;
	pt = mp_mul3d(rm,pt);
	pt = mp_mul3d(cita,pt);
	pt = mp_mul3d(phi,pt);
	pt = mp_mul3d(lambda,pt);
	center = get_globe_position3d(pt);

	new_center.x = conv_unit(&er,
		r->h.cu.uenv,
		center.x,
		l_string(std_cm,"rad"),
		r->h.cu.unit);
	new_center.y = conv_unit(&er,
		r->h.cu.uenv,
		center.y,
		l_string(std_cm,"rad"),
		r->h.cu.unit);

	pt_old.x = pt_old.z = 0;
	pt_old.y = 1;
	pt = pt_old;

	pt = mp_mul3d(rm,pt);
	pt = mp_mul3d(cita,pt);
	pt = mp_mul3d(phi,pt);
	pt = mp_mul3d(lambda,pt);

	get_round_matrix3d_lambda(lambda,-center.x);
	get_round_matrix3d_phi(phi,-center.y);

	pt = mp_mul3d(lambda,pt);
	pt = mp_mul3d(phi,pt);

	/* new_rotate = kakudo of y axis and pt */

	if ( pt.x || pt.y ) {
		if ( pt.x < pt.y ) {
			if ( pt.x < - pt.y ) {
				/* 2 */
				new_rotate = -M_PI/2 - atan(pt.y/pt.x);
			}
			else {
				/* 1 */
				new_rotate = atan(pt.x/pt.y);
			}
		}
		else {
			if ( pt.x < - pt.y ) {
				/* 3 */
				if ( pt.x < 0 ) {
					new_rotate = -M_PI + atan(pt.x/pt.y);
				}
				else {
					new_rotate = M_PI + atan(pt.x/pt.y);
				}
			}
			else {
				/* 4 */
				new_rotate = M_PI/2 - atan(pt.y/pt.x);
			}
		}
	}
	else	new_rotate = 0;


printf("NEW %f %f - %f\n",new_center.x,new_center.y,new_rotate);
	env.flame_base_center = new_center;
	env.flame_base_rotate = new_rotate;
	calc_pitch(1);
	return 0;
}


void
wf_move_si_globe(WIN_FLAME * wf,GLOBE_MOVE_T *t)
{
GB_RECT r;
SYMBOL_INDICATE ** sip, * si1;
GB_POINT3D p;
double d,sq_radius;
int dx,dy;
	r.tl.x = r.tl.y = 0;
	r.br.x = env.win_width;
	r.br.y = env.win_height;
	sq_radius = t->radius * t->radius;
	for ( sip = &wf->sym_i ; *sip ; ) {
		si1 = *sip;
		p.x = si1->rect.tl.x;
		p.y = si1->rect.tl.y;
		d = p.x * p.x + p.y * p.y;
		if ( d > sq_radius )
			goto del;
		p.z = sqrt(sq_radius - d);
		p = mp_mul3d(t->rm,p);
		if ( p.z < 0 )
			goto del;
		dx = p.x - si1->rect.tl.x;
		dy = p.y - si1->rect.tl.y;

		si1->rect.tl.x += dx;
		si1->rect.br.x += dx;
		si1->rect.tl.y += dy;
		si1->rect.br.y += dy;
		if ( cross_rect_rect(&r,&si1->rect) == 1 ) {
			sip = &(*sip)->next;
			continue;
		}
	del:
		*sip = si1->next;
		if ( si1->data )
			d_f_ree(si1->data);
		if ( si1->alpha )
			d_f_ree(si1->alpha);
		if ( si1->rect.tl.x == si1->rect.br.x )
			delete_irq(si1->rno,si1->code);

		d_f_ree(si1);
	}
}


int
globe_move(WIN_FLAME * wf,GB_POINT from,GB_POINT to,GLOBE_MOVE_T * t)
{
unsigned long * dest;
int w,h;
extern int null_wf_spiral;

set_t_msg(2531);
	w = env.win_width;
	h = env.win_height;
	dest = d_alloc(sizeof(unsigned long)*w*h,1235);
set_t_msg(2532);
set_t_msg2(t);
printf("IX-2 %x %x\n",wf->pixels,t);
	index_move(dest,wf->pixels,t->ix,w,h,BACKGROUND_COLOR|C_DIRTY,
			C_DIRTY);
set_t_msg(2533);
	wf_move_si_globe(wf,t);
set_t_msg(2534);
	d_f_ree(wf->pixels);
	wf->pixels = dest;
	null_wf_spiral = 1;
	if ( wf->flags & WFF_LUSTER )
		wf->flags |= WFF_LUSTER_DIRTY;
	if ( wf->flags & WFF_POLY )
		wf->flags |= WFF_POLY_DIRTY;
	if ( wf->flags & WFF_PLOT )
		wf->flags |= WFF_PLOT_DIRTY;
set_t_msg(2535);
	return 0;
}


int
globe_move_plot(WIN_FLAME * wf,GB_POINT from,GB_POINT to,GLOBE_MOVE_T * t)
{
	wf_move_si_globe(wf,t);
	if ( wf->flags & WFF_PLOT )
		wf->flags |= WFF_PLOT_DIRTY;
	return 0;
}
