/*
 * Header Begins--Do not remove################################################
 *
 *	C-code stub for the plotting package.  Look at the drivers for
 *	examples of the use of these functions.
 *
 *	(c) Eugene Fiume, University of Toronto, 1995.
 *
 *	You are permitted to use this code for noncommercial, educational
 *	purposes only.  This header must not be removed from this file.
 *
 * Header Ends--Do not remove##################################################
 */

#include "Plot.h"
#include <math.h>

static RealPoint3D	Rotation = {0.0,0.0,0.0};
static int		DoRotation = FALSE;
static RealPoint2D	Scale    = {100.0,100.0};
static IntPoint2D	Offset   = {300,100};
static int		Colour   = 1;


void SetRotation(x,y,z)
	double x,y,z;
{
	Rotation.x = x;
	Rotation.y = y;
	Rotation.z = z;
	DoRotation = TRUE;
} /* SetRotation */


void SetScale(x,y)
	double x,y;
{
	Scale.x = x;
	Scale.y = y;
} /* SetScale */


void SetOffset(x,y)
	int x,y;
{
	Offset.x = x;
	Offset.y = y;
} /* SetOffset */


void SetColour(c)
	int c;
{
	Colour = c;
} /* SetColour */



/*
 *
 *	These routines rotate points about the x,y,z axes.
 *	The function ApplyRotations below rotates a point about all three
 *	axes
 *
 */

static RealPoint3D RotatePtZ(pt, ang)
	RealPoint3D pt;
	double ang;
{
	double s,c;
	RealPoint3D p;

	s = sin(ang);
	c = cos(ang);

	p.z = pt.z;
	p.x = c*pt.x - s*pt.y;
	p.y = s*pt.x + c*pt.y;
	return(p);
} /* RotatePtZ */



static RealPoint3D RotatePtY(pt, ang)
	RealPoint3D pt;
	double ang;
{
	double s,c;
	RealPoint3D p;

	s = sin(ang);
	c = cos(ang);

	p.y = pt.y;
	p.x = c*pt.x + s*pt.z;
	p.z = -s*pt.x + c*pt.z;
	return(p);
} /* RotatePtY */



static RealPoint3D RotatePtX(pt, ang)
	RealPoint3D pt;
	double ang;
{
	double s,c;
	RealPoint3D p;

	s = sin(ang);
	c = cos(ang);

	p.x = pt.x;
	p.y = c*pt.y - s*pt.z;
	p.z = s*pt.y + c*pt.z;
	return(p);
} /* RotatePtX */




static RealPoint3D ApplyRotations(pt)
	RealPoint3D pt;
{
	if (DoRotation)
		return(RotatePtZ(RotatePtY(RotatePtX(pt,Rotation.x),
			Rotation.y), Rotation.z));
	else
		return(pt);
} /* ApplyRotations */


/*
 *
 *	This routine takes a 2D real co-ordinate and converts it to an integer
 *	pixel address.  Note that the user-set Scale factor and Offset are
 *	applied here.
 *
 */

static IntPoint2D ConvertToScreen(p)
	RealPoint2D p;
{
	IntPoint2D i;

	i.x = round(Scale.x*p.x) + Offset.x;
	i.y = round(Scale.y*p.y) + Offset.y;
	return(i);
} /* ConvertToScreen */



/*
 *
 *	R3DtoR2D technically simply takes the x and y component from a 3D point
 *	and returns a 2D point.  What it really does is perform an orthographic
 *	projection of a point P(x,y,z) in space onto a point (x,y) on the screen.
 *	
 *	
 *	The combination of:
 *		ConvertToScreen(R3DtoR2D(P))
 *	
 *	returns a pixel value on the screen (that can be used to draw lines with).
 *	
 *	You will need ConvertToScreen for both 2D and 3D plotting.
 *	You will need R3DtoR2D only for 3D plotting.
 *	
 */


static RealPoint2D R3DtoR2D(p)
	RealPoint3D p;
{
	RealPoint2D q;
	q.x = p.x;
	q.y = p.y;
	return(q);
} /* R3DtoR2D */



static void Line(p0,p1)
	RealPoint2D p0,p1;
{
	IntPoint2D i0,i1;

	i0 = ConvertToScreen(p0);
	i1 = ConvertToScreen(p1);
	drawline(i0.x, i0.y, i1.x, i1.y, Colour);
} /* Line */



/*
 *	You will be implementing the following plot routines as described
 *	in the Assignment 1 handout and news postings.  Remember that Plot3D
 *	must be efficient in that no line segment should be drawn more than
 *	once and no function evaluation for a specific (s,t) should be
 *	performed more than once.  Notice that both of these routines take
 *	function pointers as arguments.  Have a look at the drivers to see
 *	how this works.  To execute a function within Plot2D or Plot3D
 *	that is passed in this way, you simply type, for example, "x(s,t)".
 */
void Plot2D(x,y, t0,t1, nt)
	double	(*x)(), (*y)();
	double	t0, t1;
	int	nt;
{
} /* Plot2D */



void Plot3D(x,y,z, t0,t1, nt, s0,s1, ns)
	double	(*x)(), (*y)(), (*z)();
	double	t0, t1;
	int	nt;
	double	s0, s1;
	int	ns;
{
} /* Plot3D */

/* end  of  Plot  module */
