/* 
 * WicketTest.c - test program for vertex abstract data type.
 * 
 * Author:	L. Van Warren
 * Date:	April 1984
 * Copyright (c) 1984 L. Van Warren * All Rights Reserved
 * 
 */
#include "Van.h"

#define A_POS	asnVec(0.5, 0.8, 0.0, 1.0)
#define B_POS	asnVec(0.8, 0.2, 0.0, 1.0)
#define C_POS	asnVec(0.2, 0.2, 0.0, 1.0)

#define A_NRM	nrmVec(asnVec(  0.0,  0.0, -1.0, 0.0))
#define B_NRM	nrmVec(asnVec(  0.0,  0.0, -1.0, 0.0))
#define C_NRM	nrmVec(asnVec(  0.0,  0.0, -1.0, 0.0))

#define A_CLR	asnVec(1.0,0.2,0.2,1.0)
#define B_CLR	asnVec(0.2,1.0,0.2,1.0)
#define C_CLR	asnVec(0.2,0.2,1.0,1.0)

#define A_NTUV	asnVec(0.0,4.0,7.0,1.0)
#define B_NTUV	asnVec(1.0,5.0,8.0,2.0)
#define C_NTUV	asnVec(2.0,6.0,9.0,3.0)

extern void testWicket(void);
extern void testLrpVrt2(void);
extern void testLrpVrt3(void);
extern void testRayCorrect(void);
extern void testRayDrawing(void);
extern void testRaySpray(void);
extern ImgX    drawTriangle(ImgX, Vrt, Vrt, Vrt);
extern ImgX rcrDrawTriangle(ImgX, Vrt, Vrt, Vrt, int);
extern void testWicketIO(void);
extern void testWicketTiming(void);

/*extern void testWicket(void);

extern void testRays(void);
extern void testLirpVrt3Text3Text(Wicket, Wicket, Wicket, Vec);*/

void testBTbl(void);
void testBTblCorrect(void);
void testBTblIO(void);
void testBTblTiming(void);

void testWicket(void)
{
	int portion;
	
	fprintf(stdout, "Wickets (Vertices, Lines, Rays & Transfer Functions) \n");
    
	while(1)
	{
			
		fprintf(stdout, "0) Return\n");
		fprintf(stdout, "1) Vertex Linear      Interpolation and Line Drawing\n");
		fprintf(stdout, "2) Vertex Barycentric Interpolation\n");
		fprintf(stdout, "3) Ray Reflecting and Refracting Text Test\n");
		fprintf(stdout, "4) Ray Reflecting and Refracting Drawing\n");
		fprintf(stdout, "5) Bucket Sorting and Radial Ray Spray\n");
		fprintf(stdout, "6) Wicket I/O\n");
		fprintf(stdout, "7) Wicket Timing\n");
		fprintf(stdout, "Press a number to test a package.\n");
		
		fscanf(stdin, "%d", &portion);
		
		fprintf(stdout, "You typed %d.\n", portion);
	
		switch(portion)
		{
			case 0:
				return;
			break;
			
			case 1:
				testLrpVrt2();
			break;
		
			case 2:
				testLrpVrt3();
			break;
			
			case 3:
				testRayCorrect();
			break;
			
			case 4:
				testRayDrawing();
			break;
			
			case 5:
				testRaySpray();
			break;
			
			case 6:
				testWicketIO();
			break;
			
			case 7:
				testWicketTiming();
			break;
						
			default:
				fprintf(stdout, "No such choice as %d\n", portion);
			break;
		}
	}
}

void
testLrpVrt2(void)
{
	ImgX imgX;
	Vrt A, B, C;
	
	imgX = AsgnX("Vertex Lirping", IMGX, IMGY);
	
	A = asnWicket(VRT_KIND, A_POS, A_NRM, A_CLR, A_NTUV);	
	B = asnWicket(VRT_KIND, B_POS, B_NRM, B_CLR, B_NTUV);
	C = asnWicket(VRT_KIND, C_POS, C_NRM, C_CLR, C_NTUV);

	imgX = rcrDrawTriangle(imgX, A, B, C, 0);
	
	ViewX(imgX, WINX, WINY);
}

ImgX
rcrDrawTriangle(ImgX imgX, Vrt A, Vrt B, Vrt C, int level)
{
	Vrt AB, BC, CA;
	
	if(level <  5)
	{		
		AB = lrpVrt2(A, B, 0.5);
		BC = lrpVrt2(B, C, 0.5);
		CA = lrpVrt2(C, A, 0.5);
	
		imgX = rcrDrawTriangle(imgX,  A, AB, CA, level + 1);
		imgX = rcrDrawTriangle(imgX, AB,  B, BC, level + 1);
		imgX = rcrDrawTriangle(imgX, CA, BC,  C, level + 1);
	}
	else
	{
	 	imgX = drawTriangle(imgX, A, B, C);
	}
	
	return(imgX);
}

ImgX
drawTriangle(ImgX imgX, Vrt A, Vrt B, Vrt C)
{	
	imgX = LineX(imgX, A, B);
	imgX = LineX(imgX, B, C);
	imgX = LineX(imgX, C, A);

	return(imgX);
}

void
testLrpVrt3(void)
{
	int i;
	ImgX imgX;
	Vrt A, B, C, baryCenter;
	Vec d_pos;
	
	imgX = AsgnX("Barycentric Lirping", 300, 300);
	
	A = asnWicket(VRT_KIND, A_POS, A_NRM, A_CLR, A_NTUV);	
	B = asnWicket(VRT_KIND, B_POS, B_NRM, B_CLR, B_NTUV);
	C = asnWicket(VRT_KIND, C_POS, C_NRM, C_CLR, C_NTUV);

	imgX = drawTriangle(imgX, A, B, C);
	
	for(i = 0; i < 60; i++)
	{
		d_pos = asnVec(0.5+GaussianRand()/4, 0.5+GaussianRand()/4, 0.0, 1.);
		
		baryCenter = lrpVrt3(A, B, C, d_pos);
		
		imgX = LineX(imgX, A, baryCenter);
		imgX = LineX(imgX, B, baryCenter);
		imgX = LineX(imgX, C, baryCenter);
	}
	
	ViewX(imgX, WINX, WINY);
}


void
testRaySpray(void)
{
	float theta;
	Ray  ray;
	ImgX imgX;
	
	imgX = AsgnX("Radial Spray", 300, 300);
	
	for(theta = 0.0; theta < (2.0*MATH2_PI); theta += (MATH2_PI/5.0))
	{	
		ray = asnWicket(RAY_KIND, A_POS, nrmVec(asnVec(cos(theta),sin(theta),0,0)), A_CLR, A_NTUV);
		imgX = RayeX(imgX, ray);		
		ViewX(imgX, WINX, WINY);
	}	
	
	FreeX(imgX);
	
	return;
}

void
testRayDrawing (void)
{
	float theta;
	Ray  rayIn, rayOut;
	Xfr  xfr;
	ImgX imgX;
	
	imgX = AsgnX("Bounding", 300, 300);
		
	for(theta = 0.0; theta < (2.0*MATH2_PI); theta += (MATH2_PI/.5))
	{		
		rayIn = asnWicket
		(
			RAY_KIND,                      /* this wicket is a ray    */
			asnVec(0, 0, 0,  1 ),          /* origination             */
			nrmVec(asnVec(0.5, 1, 0,  0)), /* direction components    */
			asnVec( 1, 1, 1,  1 ),         /* propagating white light */
			A_NTUV                         /* non-attenuating media   */
		);
		
		xfr = asnWicket
		(
			XFR_KIND,                      /* this wicket is a transfer function */
			asnVec( 0.5,0.999, 0, 1),      /* intersection point                 */
			asnVec( 0, -1, 0, 0),          /* normal   components               */
			asnVec( 1, 0, 0, 1),           /* transferring red  light            */
			C_NTUV                         /* glass to air refractive index      */
		);

		imgX = RayeX(imgX, rayIn);
		ViewX(imgX, WINX, WINY);
		
		rayOut = reflected(rayIn, xfr); fprintWicket(stdout, rayOut);

		imgX = RayeX(imgX, rayOut);
		ViewX(imgX, WINX, WINY);
	}	
	
	FreeX(imgX);
	
	return;		
}

void
testRayCorrect (void)
{
	Ray rayIn, rayOut, rayOk;
	Xfr xfr;
	double x, y;
 	
	fprintf(stdout, "RAY BOUNCING TEST\n");
	fprintf(stdout, "CASE ONE: Front reflection\n");
	
	rayIn = asnWicket
	(
		RAY_KIND,              /* this wicket is a ray    */
		asnVec(-1, 0, 0,  1 ), /* origination             */
nrmVec( asnVec( 1,-1, 0,  0)), /* direction components    */
		asnVec( 1, 1, 1,  1 ), /* propagating white light */
		A_NTUV                 /* non-attenuating media   */
	);
	
	xfr = asnWicket
	(
		XFR_KIND,            /* this wicket is a transfer function */
		asnVec( 0,-1, 0, 1), /* intersection point                 */
		asnVec( 0, 1, 0, 0), /* direction components               */
		asnVec( 1, 0, 0, 1), /* transferring red  light            */
		C_NTUV               /* glass to air refractive index      */
	);
	
	rayOut = reflected(rayIn, xfr);
	
	fprintf(stdout, "Outgoing ray is:\n");
	
	fprintWicket(stdout, rayOut);
	
	fprintf(stdout, "Outgoing ray should be:\n");
	
	rayOk = asnWicket
	(
		FRNT_REFL,             /* this wicket is a ray    */
		asnVec( 0,-1, 0,  1 ), /* origination             */
nrmVec( asnVec( 1, 1, 0,  0)), /* direction components    */
		asnVec( 1, 0, 0,  1 ), /* propagating red   light */
		A_NTUV                 /* non-attenuating media   */
	);
	
	fprintWicket(stdout, rayOk);
	
	fprintf(stdout, "CASE TWO: Back reflection\n");
	
	xfr = asnWicket
	(
		XFR_KIND,            /* this wicket is a transfer function */
		asnVec( 0,-1, 0, 1), /* intersection point                 */
		asnVec( 0,-1, 0, 0), /* direction components               */
		asnVec( 1, 0, 0, 1), /* transferring red  light            */
		C_NTUV               /* glass to air refractive index      */
	);
	
	rayOut = reflected(rayIn, xfr);
	
	fprintf(stdout, "Outgoing ray is:\n");
	
	fprintWicket(stdout, rayOut);
	
	fprintf(stdout, "Outgoing ray should be:\n");
	
	rayOk = asnWicket
	(
		BACK_REFL,             /* this wicket is a ray    */
		asnVec( 0,-1, 0,  1 ), /* origination             */
nrmVec( asnVec( 1, 1, 0,  0)), /* direction components    */
		asnVec( 1, 0, 0,  1 ), /* propagating red   light */
		A_NTUV                 /* non-attenuating media   */
	);
	
	fprintWicket(stdout, rayOk);
	
	fprintf(stdout, "CASE THREE: Front refraction: from air to glass\n");
		
	xfr = asnWicket
	(
		XFR_KIND,            /* this wicket is a transfer function */
		asnVec( 0,-1, 0, 1), /* intersection point                 */
		asnVec( 0, 1, 0, 0), /* direction components               */
		asnVec( 1, 0, 0, 1), /* transferring red  light            */
		C_NTUV               /* glass to air refractive index      */
	);

	rayOut = refracted(rayIn, xfr);
	
	fprintf(stdout, "Outgoing ray is:\n");
	
	fprintWicket(stdout, rayOut);
	
	fprintf(stdout, "Outgoing ray should be:\n");
	
	x = sin(MATH2_PI_4)/2.0;
	y = sqrt(1 - x*x);
	rayOk = asnWicket
	(
		FRNT_REFR,             /* this wicket is a ray    */
		asnVec( 0,-1, 0,  1 ), /* origination             */
nrmVec( asnVec( x,-y, 0,  0)), /* direction components    */
		asnVec( 1, 0, 0,  1 ), /* propagating red   light */
		A_NTUV                 /* non-attenuating media   */
	);
	
	fprintWicket(stdout, rayOk);
	
	fprintf(stdout, "CASE FOUR: Back refraction: from air to glass\n");
		
	xfr = asnWicket
	(
		XFR_KIND,             /* this wicket is a transfer function */
		asnVec( 0,-1, 0, 1), /* intersection point                  */
		asnVec( 0,-1, 0, 0), /* direction components                */
		asnVec( 1, 0, 0, 1), /* transferring red  light             */
		C_NTUV               /* glass to air refractive index       */
	);

	rayOut = refracted(rayIn, xfr);
	
	fprintf(stdout, "Outgoing ray is:\n");
	
	fprintWicket(stdout, rayOut);
	
	fprintf(stdout, "Outgoing ray should be:\n");
	
	x = sin(MATH2_PI_4)/2.0;
	y = sqrt(1 - x*x);
	rayOk = asnWicket
	(
		BACK_REFR,             /* this wicket is a ray    */
		asnVec( 0,-1, 0,  1 ), /* origination             */
nrmVec( asnVec( x,-y, 0,  0)), /* direction components    */
		asnVec( 1, 0, 0,  1 ), /* propagating red   light */
		A_NTUV                 /* non-attenuating media   */
	);
	
	fprintWicket(stdout, rayOk);		
}


void
testWicketIO(void)
{
    FILE  * asc_file, *bin_file;
	Wicket a;

	fprintf(stdout, "I/O TEST\n");	

	a = asnWicket(VRT_KIND, A_POS, A_NRM, A_CLR, A_NTUV);	

    fprintWicket (stdout, a);

    fprintf (stdout, "writing vertex a to ascii file:\n");
    asc_file = fopen ("test.asc", "w");
    fprintWicket (asc_file, a);
    fclose (asc_file);

    fprintf (stdout, "reading a from ascii file:\n");
    asc_file = fopen ("test.asc", "r");
    fprintWicket (stdout, fscanWicket(asc_file));
    fclose (asc_file);

    fprintf (stdout, "writing vertex a to binary file:\n");
    bin_file = fopen ("test.bin", "w");
    fwriteWicket (bin_file, a);
    fclose (bin_file);

    fprintf (stdout, "reading a from binary file:\n");
    bin_file = fopen ("test.bin", "r");
    fprintWicket (stdout, freadWicket(bin_file));
    fclose (bin_file);
}

#define N 1000000
#define TIMEUP(label, x) {elapsed=clock()-start;fprintf(stdout, "%s %f s\n",label,(float)(elapsed)/CLOCKS_PER_SEC);x+=elapsed;}

void
testWicketTiming(void)
{
	int n;
	clock_t start, elapsed, CTotal=0;
	Wicket a, b, c;
	Ray rayIn, rayOut, xfr;

	fprintf(stdout, "TIMING TEST\n");	

    fprintf (stdout, "Vertex lrping:\n");
	a = asnWicket(VRT_KIND, A_POS, A_NRM, A_CLR, A_NTUV);	
	b = asnWicket(VRT_KIND, B_POS, B_NRM, B_CLR, B_NTUV);
	c = asnWicket(VRT_KIND, C_POS, C_NRM, C_CLR, C_NTUV);
    fprintf (stdout, "a is:\n"); fprintWicket (stdout, a);
    fprintf (stdout, "b is:\n"); fprintWicket (stdout, b);
    fprintf (stdout, "c is:\n"); fprintWicket (stdout, c);
		
	for(start = clock (), n = 0; n < N; n++)
	{ lrpVrt3 (a, b, c, sclVec (0.5, addVec (A_POS, B_POS))); }
	TIMEUP("C    (lrpVrt3):", CTotal);
		
	for(start = clock (), n = 0; n < N; n++)
	{	
		rayIn = asnWicket
		(
			RAY_KIND,              /* this wicket is a ray    */
			asnVec(-1, 0, 0,  1 ), /* origination             */
	nrmVec( asnVec( 1,-1, 0,  0)), /* direction components    */
			asnVec( 1, 1, 1,  1 ), /* propagating white light */
			A_NTUV                 /* non-attenuating media   */
		);
		
		xfr = asnWicket
		(
			XFR_KIND,            /* this wicket is a transfer function */
			asnVec( 0,-1, 0, 1), /* intersection point                 */
			asnVec( 0, 1, 0, 0), /* direction components               */
			asnVec( 1, 0, 0, 1), /* transferring red  light            */
			C_NTUV               /* glass to air refractive index      */
		);
		
		rayOut = reflected(rayIn, xfr);
	}
	TIMEUP("C    (reflected):", CTotal);
		
	for(start = clock (), n = 0; n < N; n++)
	{
		rayIn = asnWicket
		(
			RAY_KIND,              /* this wicket is a ray    */
			asnVec(-1, 0, 0,  1 ), /* origination             */
	nrmVec( asnVec( 1,-1, 0,  0)), /* direction components    */
			asnVec( 1, 1, 1,  1 ), /* propagating white light */
			A_NTUV                 /* non-attenuating media   */
		);
			
		xfr = asnWicket
		(
			XFR_KIND,            /* this wicket is a transfer function */
			asnVec( 0,-1, 0, 1), /* intersection point                 */
			asnVec( 0, 1, 0, 0), /* direction components               */
			asnVec( 1, 0, 0, 1), /* transferring red  light            */
			C_NTUV               /* glass to air refractive index      */
		);
		
		rayOut = refracted(rayIn, xfr);
	}
	TIMEUP("C    (refracted):", CTotal);
	
	fprintf(stdout, "Total elapsed time for a %d 'C' calls of 1 vertex functions %f s.\n", N, (float)CTotal/CLOCKS_PER_SEC);
}