/*************************************************************************
Copyright(c) 2004-2006 Analog Devices, Inc. All Rights Reserved.

This software is proprietary and confidential.  By using this software you agree
to the terms of the associated Analog Devices License Agreement.

File Name: adi_graph_arc.c 

Description - Part of 'adi_graph' library.  See readme file for details.

*********************************************************************************/

#include <math.h>
#include "adi_graph.h"

void EllipsePoints ( ADI_sGraphPrim *gp, bool fill )
{
	/* Four points around an origin defined by (x2,y2) and a delta of (x1,y1)*/
	int mid_x = gp->x2;
	int mid_y = gp->y2;
	int dx = gp->x1;
	int dy = gp->y1;
	
	if ( !fill )
	{
		gp->x1 = mid_x + dx;
		gp->y1 = mid_y + dy;
		ADI_Point ( gp );

		gp->x1 = mid_x + dx;
		gp->y1 = mid_y - dy;
		ADI_Point ( gp );
	
		gp->x1 = mid_x - dx;
		gp->y1 = mid_y + dy;
		ADI_Point ( gp );
	
		gp->x1 = mid_x - dx;
		gp->y1 = mid_y - dy;
		ADI_Point ( gp );
	}
	else
	{
		int x;
		
		for ( x = mid_x - dx; x <= mid_x + dx; ++x )
		{
			gp->y1 = mid_y - dy;
			gp->x1 = x;
			
			ADI_PointConsideringFillPattern ( gp );
#if 0
			
			if ( ADI_FILL_SOLID == gp->fill_style )
			{
				ADI_Point ( gp );
			}
			else
			{
				if ( gp->fill_pattern [ gp->y1 % 8 ] & ( 1 << ( gp->x1 % 8 ) ) )
				{
					ADI_Point ( gp );
				}
				else if ( ADI_FILL_OPAQUE == gp->fill_style )
				{
					int fg_color_cache = gp->fg_color;
					gp->fg_color = gp->bg_color;
					ADI_Point ( gp );
					gp->fg_color = fg_color_cache;
				}
				
			}
#endif			
			gp->y1 = mid_y + dy;
			ADI_PointConsideringFillPattern ( gp );
#if 0
			if ( ADI_FILL_SOLID == gp->fill_style )
			{
				ADI_Point ( gp );
			}
			else
			{
				if ( gp->fill_pattern [ gp->y1 % 8 ] & ( 1 << ( gp->x1 % 8 ) ) )
				{
					ADI_Point ( gp );
				}
				else if ( ADI_FILL_OPAQUE == gp->fill_style )
				{
					int fg_color_cache = gp->fg_color;
					gp->fg_color = gp->bg_color;
					ADI_Point ( gp );
					gp->fg_color = fg_color_cache;
				}
				
			}
#endif
		}
	}
		
#if 0
		for ( 
		gp->x1 = mid_x + dx;
		gp->y1 = mid_y + dy;
		gp->x2 = mid_x + dx;
		gp->y2 = mid_y - dy;
		//ADI_Line ( gp, NULL );
		
	
		gp->x1 = mid_x - dx;
		gp->y1 = mid_y + dy;
		gp->x2 = mid_x - dx;
		gp->y2 = mid_y - dy;
		//ADI_Line ( gp, NULL );		
		
		/* Restore (x2, y2) */
		gp->x2 = mid_x;
		gp->y2 = mid_y;
		}
#endif
}

void MidpointEllipse ( ADI_sGraphPrim *gp, bool fill )
{
	int x, y, d1, d2;
	
	/* (a,b) defines the width and height of the ellipse*/
	const int a = gp->x1;
	const int b = gp->y1;
	
	x = 0;
	y = gp->y1;
	gp->x1 = x; gp->y1 = y; EllipsePoints ( gp, fill );
	
	d1 = b*b - a*a*b + a*a/4;
	while ( a*a*y > b*b*(x+1) )
	{
		if ( d1 < 0 )
		{
			d1 += b*b*(2*x+3);
			++x;
		}
		else
		{
			d1 += b*b*(2*x+3)+a*a*((-2)*y+2);
			++x;
			--y;
		}
		
		gp->x1 = x; gp->y1 = y; EllipsePoints ( gp, fill );
	}
	
	d2 = b*b*x*(x+1)+a*a*(y-1)*(y-1)-a*a*b*b;
	while ( y > 0 )
	{
		if ( d2 < 0 )
		{
			d2 += b*b*(2*x+2)+a*a*((-2)*y+3);
			++x;
			--y;
		}
		else
		{
			d2 += a*a*((-2)*y+3);
			--y;
		}

		gp->x1 = x; gp->y1 = y; EllipsePoints ( gp, fill );
	}
}

void ADI__Arc ( ADI_sGraphPrim *gp, double start_angle, double end_angle, bool fill )
{
	int mid_x, mid_y;
	
	int x1 = gp->x1;
	int x2 = gp->x2;
	int y1 = gp->y1;
	int y2 = gp->y2;
	
	ADI_SwapIfGreaterThan ( x1, x2 );
	ADI_SwapIfGreaterThan ( y1, y2 );
	
	mid_x = ( x1 + x2 ) / 2;
	mid_y = ( y1 + y2 ) / 2;
	
	gp->x1 = x2 - mid_x;
	gp->y1 = y2 - mid_y;
	gp->x2 = mid_x;
	gp->y2 = mid_y;
	
	MidpointEllipse ( gp, fill );
}

void ADI_Arc ( ADI_sGraphPrim *gp, double start_angle, double end_angle )
{
	return ADI__Arc ( gp, start_angle, end_angle, false );
}


void ADI_ArcFill ( ADI_sGraphPrim *gp, double start_angle, double end_angle )
{
	return ADI__Arc ( gp, start_angle, end_angle, true );
}

