/*
*	Yamana's Otomeza Plug-in Tool
*		３点指定円
*	
*	1995.08.20
*	1995.08.26	手ぶれんビ〜搭載(^^;)
*	
*/
#include	"otome_pi.h"
#include	"costbl.h"

const char longname[] = "DRAW  : ３点指定円";
int			cnfg_max = 2;
PI_CNFG		cnfg[] = {
				{"楕円      正円"	, 0,  1,  0,  0 },
				{"線の太さ"			, 1, 32,  1,  1 }
			};

#define	USE_ENV		PI_SET_ENV
#define	USE_TYPE	PI_EFFC_POLY
#include	"otome_pi.c"

/* 手ぶれとする値 */
#define		TEBURE		3

/*******************************************************/

POINT	Points[3];


/* ３点の座標を得る */
int get_Points()
{
	int ox,oy,i,j;
	
	if( WORD(g_para) < 3 )
		return ERROR;
	
	memcpy( &Points[0], g_para+2, 2*2 );	/* 第１点 */
	
	/* 手ぶれによって点が接近している場合があるので補正する。*/
	i = 0;
	j = 0;
	while( j<2)
	{	do
		{	i++;
			ox = WORD( g_para+i*4+2 );
			oy = WORD( g_para+i*4+4 );
			
		}while( abs(ox-Points[j].x)<=TEBURE
			 && abs(oy-Points[j].y)<=TEBURE	&& i<WORD(g_para) );
		
		if( i >= WORD(g_para) )	return ERROR;
		j++;
		Points[j].x = ox;
		Points[j].y = oy;
	}
	return NOERR;
}

/*******************************************************/

int circle_3Points()
{
	char	tmp[2*2];
	
	EGB_bow( EgbPtr, &Points );
	
	/* ２点目と３点目を入れ替えて再実行するだけ */
	memcpy( tmp,			&Points[1].x,	2*2 );
	memcpy( &Points[1].x,	&Points[2].x,	2*2 );
	memcpy( &Points[2].x,	tmp,			2*2 );
	
	EGB_bow( EgbPtr, &Points );
	
	return NOERR;
}

/* 128角形を楕円変形し回転させる */
/* 256角形にしても速度差はほとんどないが、誤差が拡大されてしまう */
#define	EN_P	128

int circle_slant()
{
	register int 	x,y;
	int 	t,ox,oy,step;
	int 	rx,ry,r,rby;
	int 	rsin,rcos;
	char	*para,*p;
	
	if( (para=(char*)PI_MALLOC( 2+ EN_P*4 ))==NULL )
		return PI_ERROR_NO_MEMORY;
	
#ifdef	DEBUG
	printf("(%d,%d)-(%d,%d)-(%d,%d)",
		Points[0].x,Points[0].y,
		Points[1].x,Points[1].y,
		Points[2].x,Points[2].y		);
#endif
	
	/* 最初の２点間の距離÷２を楕円の１つ目の軸長とする */
	x = (Points[0].x - Points[1].x);
	y = (Points[0].y - Points[1].y);
	rx = sqrt( x*x + y*y )/2;
	
	/* 中心点 */
	ox = (Points[0].x + Points[1].x)/ 2 ;
	oy = (Points[0].y + Points[1].y)/ 2 ;
	
	/* 中点と３点目の距離を楕円の２つ目の軸長とする */
	x = (Points[2].x - ox);
	y = (Points[2].y - oy);
	ry = sqrt( x*x + y*y );
	
	rby = 256*ry/rx;
	
	/* 回転角 */
	rsin = ((oy - Points[1].y)<<8 )/ ry;
	rcos = ((ox - Points[1].x)<<8 )/ ry;
	r = ry;
	
	step = 256 / EN_P;
	WORD( para ) = EN_P+1 ;
	p = para+2;
	for( t=0 ; t<= 256 ; t+=step,p+=4 )
	{
		x = (r * cos256( t ) );
		y = (r * sin256( t ) * rby + 0x80 >>8 );	/* 四捨五入 */
		
		WORD( p   ) = ox + ((x*rcos - y*rsin) >>16) ;
		WORD( p+2 ) = oy + ((x*rsin + y*rcos) >>16) ;
	}
	
	EGB_connect( EgbPtr, para );
	
	PI_FREE( para );
	
	return NOERR;
}

/*************************************/

int APL_exec()
{
	int 	mode,pen,ret;
	
	mode = cnfg[0].val;
	pen  = cnfg[1].val;
	
	if( get_Points() )	return ERROR;
	
	EGB_writePage( EgbPtr, PI_PAGE );
	EGB_writeMode( EgbPtr, EGB_PSET );
	
	/* タイル指定を有効に */
	if( PI_TILEFLG )
	{	EGB_tilePattern( EgbPtr, EGB_FORECOL,
					PI_TILE_X, PI_TILE_Y, PI_TILE_PAT );
		EGB_paintMode( EgbPtr, EGB_PAINT_TILE );
	}else
	{	EGB_color( EgbPtr, EGB_FORECOL,  PI_FORECOL );
		EGB_paintMode( EgbPtr, EGB_PAINT_BETA );
	}
	EGB_penSize( EgbPtr, pen );
	
	
		 if( mode==0 )	return circle_slant();
	else if( mode==1 )	return circle_3Points();
	else 				return ERROR;
	
}

