/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:ellipse.c 12.0$ */
/* $ACIS:ellipse.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/ditroff/dit3812/RCS/ellipse.c,v $ */

#ifndef lint
static char *rcsid = "$Header:ellipse.c 12.0$";
#endif

/* ellipse generator */

#include <pmp/vector.h>
#include <pmp/pmp.h>
#include <stdio.h>

/* 
 * Restricted ellipse generator. Assumes centered at current point,
 * with normalized x/y axes (no rotation).
 * Uses the equation f(x,y) = b*b*x*x + a*a*y*y -a*a*b*b = 0
 * where 2a is the x diameter and 2b is the y diameter.
 *
 * From "Curve-Drawing Algorithms for Raster Displays", Van Aken & Novak,
 * ACM Transactions on Graphics, Vol. 4, No. 2, April 1985, pp 147-169
 */

ellipse(diamx,diamy)
	int diamx, diamy;
{
	int a,b,x,y;
	register int d1,d2;
	int t1,t2,t3,t4,t5,t6,t7;
	register int t8,t9;
	int dx,dy,ox,oy;

	cursor_reg *startcr1,*startcr2;
        vectors *quad1,*quad2,*quad3,*quad4;
	int save_ends;

	save_ends = v_set_dflt_ends(P_VECTOR_ROUND_ENDS);
	startcr1 = p_cr_mark();
	quad1 = v_new();
	quad2 = v_new();
	quad3 = v_new();
	quad4 = v_new();

	a = diamx >> 1;
	b = diamy >> 1;
	x = a ;  y = 0;
	ox = a; oy = 0;
/* set up temporary variables used to eliminate inner-loop multiplies */
	t1 = a*a;
	t2 = t1 << 1;
	t3 = t2 << 1;
	t4 = b*b;
	t5 = t4 << 1;
	t6 = t5 << 1;
	t7 = a*t5;
	t8 = t7 << 1;
	t9 = 0;
/* initialize epsilon variables */
	d1 = t2 - t7 + (t4 >> 1);
	d2 = (t1 >> 1) - t8 + t5;

while (d2<0)
	{			/* region 1 of ellipse */
	dx = ox - x;
	dy = oy - y;
	v_draw(quad1,dx,dy);
	v_draw(quad2,dx,-dy);
	v_draw(quad3,-dx,-dy);
	v_draw(quad4,-dx,dy);
	ox = x;
	oy = y;
	y++;			/* always increment y */
	t9 += t3;
	if (d1<0)
		{		/* step to pixel D */
		d1 += t9 + t2;
		d2 += t9;
		}
	else			/* step to pixel C */
		{
		x--;
		t8 -= t6;
		d1 += (t9 + t2 - t8);
		d2 += (t5 + t9 - t8);
		}
	}
do
	{			/* region 2 of ellipse */
	dx = ox - x;
	dy = oy - y;
	v_draw(quad1,dx,dy);
	v_draw(quad2,dx,-dy);
	v_draw(quad3,-dx,-dy);
	v_draw(quad4,-dx,dy);
	ox = x;
	oy = y;
	x--;			/* always decrement x */
	t8 -= t6;
	if (d2<0)	
		{		/* step to pixel C */
		y++;
		t9 += t3;
		d2 += (t5 + t9 - t8);
		}
	else			/* step to pixel B */
		d2 += (t5 - t8);
	}
while (x >= 0);
	p_cr_return(startcr1,P_KEEP_CURSOR_REG);
 	p_draw_vectors(quad1);
	p_cr_return(startcr1,P_KEEP_CURSOR_REG);
	p_draw_vectors(quad2);
	p_cr_return(startcr1,P_FREE_CURSOR_REG);
	p_mv_relative(a+a,0);
	startcr2 = p_cr_mark();
	p_draw_vectors(quad3);
	p_cr_return(startcr2,P_KEEP_CURSOR_REG);
	p_draw_vectors(quad4);
	p_cr_return(startcr2,P_FREE_CURSOR_REG);
	v_free(quad1);
	v_free(quad2);
	v_free(quad3);
	v_free(quad4);
	v_set_dflt_ends(save_ends);
}
