COM1370, Computer Graphics, Summer 1998, Professor Futrelle


The first part of this file is the PA2 assignment description, as emailed.
This is followed by all the source files concatenated together.

This assignment for smooth animation, PA2, is due Monday, August 10.
Since a lot of your sources will be identical to mine, please hand in
only the sources of the files you changed, as well as a Mac floppy with
your project which runs under Code Warrior for the Mac.

I handed out hardcopy in class on Thursday of all the sources for the
"smoothy" project.  I have also put the project, all the sources, etc.
on Ambassador.  The project, which I was unable to demo in class (cart
Mac problems) shows a moving read circle in the left window and a
non-flickering version in the right window.  This is because the
window pixels are all moved rapidly to the right window after the
update is finished in the left window (using bitblt == bit block
transfer).  In addition, the demo rotates a line using a 3x3 matrix
(homogeneous coordinates), and draws a triangle to demonstrate polygon
drawing.

Your programming assignment 2, PA2, has two requirements.  You should
use all of my Smoothy code you can, don't display any of the things
currently in it, and make changes as necessary to meet the two
requirements below.

1.  Display two or more rotating star-shaped or gear-shaped polygons
in the left window whose "teeth" interdigitate like the teeth of a
gear, as the rotate around their centers.  Bitblt the image to the
right-hand window after each update, to give a smooth animation.  As I
explained, to rotate a polygon, you rotate each point on the polygon
and then create a new polygon and display it, just as I did for the
static triangle.  You just do it repeatedly with slightly different
coordinates each time.

2.  Draw your objects with the smallest number of integer parameter
values you can use and still have an interesting image.  That is,
re-use a few basic parameters as much as possible.  For example, you
could take a basic length parameter L, say 100.  Your windows could
each be 2L by 3L.  Your two stars could each have diameter L and then
could overlap by a fraction F, so that there centers are (2 - F)L
apart.  The diameter of the "hub" of the stars could be L/2, and so
forth.  The number of "teeth" T could be 4.  The centers would be
horizontally aligned across the window and centered between the top
can bottom of the window.  The entire static part of the image would
require only three parameters.  Changing those would change your
entire image in a coordinated way.  Then you'd need to have a few
parameters for the angle between rotational steps and the total angle
of number of steps taken.

To demonstrate that your parameterized formulation works.  Show two
runs with different values of your parameters, e.g., of L and F.  You
may want to choose a different set of parameters, but the goal is to
avoid hardcoding in many, many integers, because the slightest change
could force you to go back in and change many values, in coordinated
ways.
		
		
/* 
File:	ALL-SMOOTHY-SOURCES.doc
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	This is not a file that's compiled.  It simply concatenates together
				all the source files from the working/commented project smoothy..
				These demonstrate smooth animation, bitblt-ing, polygons, sized text,
				pauses and mouse clicks, and 2D rotations using vectors and matrices
				in homogeneous coordinates.
				
				This project also demonstrates how to organize a large number of files
				including declarations, definitions, globals, and main() in a consistent
				way that can grow easily and safely, or be adapted to other projects (see
				more notes below).

Modification history:
1/25/98:	New.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// The descriptions of the files just below is also included at the
// beginning of main.cp

/*
The dependency chain has various branches, but is basically as follows
(illustrated for the graphics classes):

Forward references (bare declares) in:	graphics_classes_declares.h

Definitions of classes in:				graphics_classes.h

Definitions of member functions in:		graphics.cp

Ditto for other classes:				windows, linear_alg

All the headers are included in:		declarations.h
	except globals.h and lobs.h

Globals includes declarations:			globals.h
  and defines global vars.
  all .cp files include globals.h
  
General items with no other home:		utils.h and utils.cp

Functions in main() declared in:		main.h

Definitions of the main() functions:	smoothy_fns.pc

main() itself in:						main.cp

The files below are each clearly labeled and commented (the commenting took about
as long as the coding -- that's about right --  50/50).  They are roughly in build
order with the declarations first, then definitions and finally main() at the end.

This may have a few typos, since I proofread my individual files and may find typos
later and won't update both.  The copy of the machine (Ambassador) will be updated
from time-to-time.
*/

/* 
File:	graphics_classes_declares.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Declarations for the graphics classes, both abstract and concrete.
				Further details in other graphics files.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

class G_Obj;	// Abstract superclasss

class Rect_Based;	// rectangles, ovals, circles
	 
class Circle;

class Poly;

class Line_;

/* 
File:	graphics_classes.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Class declarations for graphics objects.  There are two abstract classes,
							G_Obj and Rect_Based (the latter for rectangles and ovals/circles).
							Concrete classes are Circle, Line_, and Poly (polygon).
							The member functions are in graphics.cp.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/24/98:	Line_ and Poly added.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// It's traditional to put "define" protection around these files, since they
// can end up be loaded twice, through various include paths, and that would create
// illegal duplicate definitions.  

#ifndef GRAPHICS_CLASSES_
#define GRAPHICS_CLASSES_

#include "graphics_classes_declares.h"

// Abstract class root of drawable things (lines, rectangles, polygons, text)
// All have Draw() and Erase(), always specialized.
class G_Obj{
  public:
		Point origin;
		
		void Draw();
		void Erase();
	};

// Has both a constructor and a setter for existing lines.
// [missing a color slot]
class Line_ : public G_Obj {
	public:
		int h1, v1, h2, v2;
		void Set_Line(int h1, int v1, int h2, int v2);
		void Draw();
		void Erase();
		
		Line_(int h1, int v1, int h2, int v2);
	};
	
	
// Abstract class for all Rect-based objects
// [Color not specific for fill or frame -- needs work.]
class Rect_Based: public G_Obj {
  public:
		int horz, vert;
		Rect my_rect;
		RGBColor color;
		void Set_Origin_Rect(Point origin);
	};
	
/*	not used at the moment

class Rectangle: public Rect_Based {
  public:
		Rectangle(Point loc, int height, int width);
		~Rectangle();
	 };
*/
	 
class Circle: public Rect_Based {
  public:
		int radius;

		void Set_Origin_Rect(Point origin);
		void Draw();
		void Erase();
		Circle(int radius);
	
	 };	 

class Poly: public G_Obj {
	public:
		PolyHandle my_poly_handle;
		
		void Open_Poly();
		void Close_Poly();
		
		void Draw();
		void Erase();
		
		void Dispose_Poly();
		
		Poly();
	};
	 
#endif

/* 
File:	window_classes_declares.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	This has the declaration for my window class. 
				See other windows files for details.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

class Window_C;


/* 
File:	linear_alg_classes_declares.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Contains declarations for linear algebra classes.
				See other linear_alg files for details.

Modification history:
1/24/98:	Created for line rotation.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

class Vector_s;

class Matrix_s;

void Matrix_x_Vector(Matrix_s*, Vector_s*); // matrix * vector, product

/* 
File:	graphics_classes.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Class declarations for graphics objects.  There are two abstract classes,
							G_Obj and Rect_Based (the latter for rectangles and ovals/circles).
							Concrete classes are Circle, Line_, and Poly (polygon).
							The member functions are in graphics.cp.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/24/98:	Line_ and Poly added.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// It's traditional to put "define" protection around these files, since they
// can end up be loaded twice, through various include paths, and that would create
// illegal duplicate definitions.  

#ifndef GRAPHICS_CLASSES_
#define GRAPHICS_CLASSES_

#include "graphics_classes_declares.h"

// Abstract class root of drawable things (lines, rectangles, polygons, text)
// All have Draw() and Erase(), always specialized.
class G_Obj{
  public:
		Point origin;
		
		void Draw();
		void Erase();
	};

// Has both a constructor and a setter for existing lines.
// [missing a color slot]
class Line_ : public G_Obj {
	public:
		int h1, v1, h2, v2;
		void Set_Line(int h1, int v1, int h2, int v2);
		void Draw();
		void Erase();
		
		Line_(int h1, int v1, int h2, int v2);
	};
	
	
// Abstract class for all Rect-based objects
// [Color not specific for fill or frame -- needs work.]
class Rect_Based: public G_Obj {
  public:
		int horz, vert;
		Rect my_rect;
		RGBColor color;
		void Set_Origin_Rect(Point origin);
	};
	
/*	not used at the moment

class Rectangle: public Rect_Based {
  public:
		Rectangle(Point loc, int height, int width);
		~Rectangle();
	 };
*/
	 
class Circle: public Rect_Based {
  public:
		int radius;

		void Set_Origin_Rect(Point origin);
		void Draw();
		void Erase();
		Circle(int radius);
	
	 };	 

class Poly: public G_Obj {
	public:
		PolyHandle my_poly_handle;
		
		void Open_Poly();
		void Close_Poly();
		
		void Draw();
		void Erase();
		
		void Dispose_Poly();
		
		Poly();
	};
	 
#endif

/* 
File:	window_classes.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Class declarations for windows.  Each has a Mac window in it,
				as well as redundant vars for its Rect and origin.  In_Window
				sets up for drawing in a particular window (setting Mac grafport).
				The member functions are in windows.cp.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// It's traditional to put "define" protection around these files, since they
// can end up be loaded twice, through various include paths, and that would create
// illegal duplicate definitions.  

#ifndef WINDOW_CLASSES_
#define WINDOW_CLASSES_

#include "window_classes_declares.h"

// Encapsulate a Mac window to abstract it.
class Window_C {
  public:
	WindowPtr win_ptr;
	Rect win_rect;
	Point win_origin;
	
	Window_C(Point loc, int height, int width);
	~Window_C();
	void In_Window();	// sets grafport to this window
	};



#endif

/* 
File:	linear_alg_classes.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Contains simple definitions to create a matrix to rotate
				around a point, and a vector type to work with it.
				This handles 2D vectors and transforms using 3-element vectors
				and 3x3-element matrices in homogeneous coordinates.
				The member functions are in linear_alg.cp.

Modification history:
1/24/98:	Created for line rotation.
1/25/98:	Constructor restricted to rotator
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// It's traditional to put "define" protection around these files, since they
// can end up be loaded twice, through various include paths, and that would create
// illegal duplicate definitions.  

#ifndef LINEAR_ALG_CLASSES_
#define LINEAR_ALG_CLASSES_

// names "..._s" mean "simple", the versions for now


#include "linear_alg_classes_declares.h"

class Vector_s {
	public:
	float vec[3];	// vec[2] always = 1.0, for homogeneous coordinates
	
	Vector_s(float x, float y);
	};



class Matrix_s {
	public:
	float matrix[3][3];
	
	// constructor only makes special matrix rotating around xc, yc.
	Matrix_s(float theta, float xc, float yc);
	};
	
#endif

/* 
File:	utils.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	The declarations for functions defined in utils.cp.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/22/98:	Added Time_Is_Up, fixed ran_pos_int.
1/24/98:	Pause_Ticks and Mouse_Event added.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

// Note that the utils.h is loaded after many others, so classes such as 
// Window_C are defined at that point.

void Pause_Ticks(int nticks);

bool Mouse_Event(int pause = 0);	// default can appear only once, traditionally here

int ran_pos_int(int low, int high);

int ran_pos_float(float low, float high);

bool Time_Is_Up(unsigned long end_time);

void Copy_Win_Bits(Window_C *w1, Window_C *w2);

void Clear_Window(Window_C *w);


/* 
File:	declarations.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Gathers together all important smoothy. project includes.
				Only globals.h is not here, but it includes _this_ file
				and is included by all the .cp files.

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include 
#include "window_classes_declares.h"
#include "graphics_classes_declares.h"
#include "linear_alg_classes_declares.h"
#include "window_classes.h"
#include "graphics_classes.h"
#include "linear_alg_classes.h"
#include "utils.h"


/* 
File:	globals.h
Author:	R. P. Futrelle
Date:	7/29/98

Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	This file contains external declarations for globals.
				It gets the type definitions from the headers loaded by
				including declarations.h.  Since this includes declarations.h,
				various .cp files include this as their _only_ include.

				Note that we access three system globals that must be accessed
				in the following way, in Code Warrior: 
				
					qd.thePort,  qd.screenBits, qd.randSeed
					
Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "declarations.h"

extern bool mouse_was_down; 

extern int	screen_w, screen_h, screen_mid, top_win;

extern Window_C *win_left, *win_right, *banner_win;

extern float x_min, x_max, y_min, y_max, vel_min, vel_max;

extern unsigned long startup_delay_max, run_time_max;

extern int ob_size;


/* 
File:	main.h
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Declares the basic calls in main().
				These functions are the ones defined in smoothy_fns.cp and called
				in main.cp. 

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/25/98:	Various declares added over the last two days.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "declarations.h"

void init_managers();

void init_globals();

void init_windows();
	
void Banner_();

void All_Done();

void Move_circle_simple();

void Draw_One_Poly();

void Spin_Line();



// ****************************************************
// END OF INCLUDES (.h), BEGINNING OF DEFINITION (.cp) FILES
// ****************************************************

/* 
File:	graphics.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Member function definitions for the graphics classes. 
				Only tricky/messy thing here is erasing a line by saving and
				restoring the foreground color while I set it to background
				to redraw the line in background. (The save/restore needs to
				worked on for similar drawing of other objects.)

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/24/98:	Line and polygon functionality added.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "globals.h"


//SetRect(r, left, top, right, bottom); // template from TBA


// Lines

// Create a line, putting the origin at the first endpoint
Line_::Line_(int H1, int V1, int H2, int V2)
	{ 
	h1 = H1; v1 = V1; h2 = H2; v2 = V2;
	origin.h = h1; origin.v = v1;
	}

// Virtually identical to the creation setup for a line
 void Line_::Set_Line(int H1, int V1, int H2, int V2)
	{ 
	h1 = H1; v1 = V1; h2 = H2; v2 = V2;
	origin.h = h1; origin.v = v1;
	}

void Line_::Draw()
	{
	MoveTo(h1, v1);
	LineTo(h2, v2);
	}

// Strategy is to redraw in the current background color.
// Note how RGB colors are manipulated using built-ins.
void Line_::Erase()
	{
	RGBColor fore; GetForeColor(&fore);
	RGBColor back; GetBackColor(&back);
	
	RGBForeColor(&back);	// draw in background color
	MoveTo(h1, v1);
	LineTo(h2, v2);
	
	RGBForeColor(&fore);	// restore to previous foreground color

	}
	

// Circles:

Circle::Circle(int the_radius)
	{radius = the_radius;};

// This is to reset center position to translate circle,
//  with no change in the radius.  my_rect has its values
//  changed by this.
void Circle::Set_Origin_Rect(Point center)
	{
		origin = center;
		int center_h = origin.h; int center_v = origin.v;
		SetRect(&my_rect, center_h - radius, center_v - radius, 
				center_h + radius, center_v + radius);
	};

void Circle::Draw()
	{PaintOval(&my_rect);};

void Circle::Erase()
	{EraseOval(&my_rect);};

// Polygons:

// These are a bit tricky.  The creation is not done in a member function,
//  since that would require a vector of points.  Instead we use the standard
//  QD paradigm of opening, drawing lines, and closing the polygon. 
// The poly structure can get big, so its a good idea to dispose of it after
// its last use, with Dispose_Poly which reclaims the memory.

Poly::Poly() 
	{};
	
void Poly::Open_Poly() 
	{my_poly_handle = OpenPoly();}
	
void Poly::Close_Poly()
	{ClosePoly();}

void Poly::Draw()
	{PaintPoly(my_poly_handle);}
	
void Poly::Erase()
	{ErasePoly(my_poly_handle);}
	
void Poly::Dispose_Poly()
	{KillPoly(my_poly_handle);}
	

/* 
File:	windows.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	The constructor makes a simple color window with no title bar 
				or scroll bars, initially displayed.  In_Window() makes subsequent 
				drawing appear in the window (instance).
				
Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "globals.h"

/* Here are the arguments for the new window call, from the Toolbox Assistant
   (set in C mode):

WindowPtr NewCWindow(void *wStorage, const Rect *boundsRect, 				
									 ConstStr255Param title, Boolean visible, 
									 short procID, WindowPtr behind, 
									 Boolean goAwayFlag, long refCon);
									 
Note the correspondence between the argument specs and the actual arguments used
below, for non-nil entries:

		Argument spec		Actual arg
		-------------		----------
		const Rect*			&win_rect
		Boolean visible		true
		short procID		plainDBox	(a system global - see TBA or IM)
		WindowPtr			(WindowPtr)-1L	(a long integer cast to a pointer)			
*/
									 
Window_C::Window_C(Point loc, int width, int height) {
	SetRect(&win_rect, loc.h, loc.v, 
	         loc.h + width, loc.v + height);
	win_origin = loc;
	win_ptr = 
		NewCWindow(nil, 
			&win_rect, 
	        nil,
	        true,
	        plainDBox,
	        (WindowPtr)-1L,
	        nil, 
	        nil);
	        }

void Window_C::In_Window() {
	SetPort(win_ptr);
	}
	
/* 
File:	linear_alg.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Implementation of linear algebra member functions and
				auxiliary functions.

Modification history:
1/24/98:	Created for line rotation.
1/25/98:	Finished details of rotation matrix and matrix-vec product
7/29/98:	Project is now smoothy.  -- modest changes made.


*/

#include "linear_alg_classes.h"
#include  

Vector_s::Vector_s(float x, float y)
	{
	vec[0] = x; vec[1] = y; vec[2] = 1.0;	// 1.0 because of homogeneous coords.
	}

// Constructor only makes special matrix rotating around xc, yc.
// See Hearn and Baker, eq. 5-31, pg. 193.
Matrix_s::Matrix_s(float theta, float xc, float yc)
	{
	float sn = sin(theta), cs = cos(theta);	// remember, theta is in radians
	matrix[0][0] =  cs;
	matrix[0][1] = -sn;
	matrix[0][2] =  xc * (1.0 - cs) + yc * sn;
	matrix[1][0] =  sn;
	matrix[1][1] =  cs;
	matrix[1][2] =  yc * (1.0 - cs) - xc * sn;
	matrix[2][0] =  0.0;
	matrix[2][1] =  0.0;
	matrix[2][2] =  1.0;
	}

// The auxiliary function for product of matrix * vector
// Not a member function of either.
// NOTE: THIS OVERWRITES THE VECTOR WITH THE NEW ONE
void Matrix_x_Vector(Matrix_s* m, Vector_s* v)
	{
	float vtemp[3] = {0.0, 0.0, 0.0};	// temp to avoid overwriting during sums
	for(int r = 0; r < 3; r++) {	// do rows
		for(int c =0; c < 3; c++) 	// do columns
			{
			vtemp[r] = vtemp[r] + m->matrix[r][c] * v->vec[c];
			};	// end columns
		};	// end rows
	for(int r = 0; r < 3; r++) v->vec[r] = vtemp[r];	// xfer vtemp vals to v
	}

	
/* The following was used to test the functions above, values checked in dbg
	

// rotate 50, 0 by 0.1 radians around 50, 100.  0.1 * 100 = +10,
// so should move to about 60, epsilon (y rises just a bit) 
// that's about what is seen in debug, so it looks fine.
// But I was wrong.  theta = 0.0 gave 1, -1, 1, on the diagonal, woops!
// Fixed sign error for [1][1] element. OK now.

Matrix_s  *m1 = new Matrix_s(0.1, 50.0, 100.0); 
Vector_s *v1 = new Vector_s(50.0, 0.0);
Matrix_x_Vector(m1, v1);
	
*/

/* 
File:	utils.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	Contains definitions of miscellaneous functions. The various time delay
				and wait-on-mouse functions all use event loops so that other things
				can run in the gaps, e.g., Flash-It to grab screen images of even
				animated things, e.g., to get an image of one "frame" of a rotating line.
				The use of CopyBits to aid smooth animation should be noted.

Modification history (by RPF == Futrelle, unless noted)
1/12/98:	Started as console1 to use SIOUX
1/20/98:	Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/22/98:	Added Time_Is_Up, fixed ran_pos_int.
1/24/98:	Pause_Ticks and Mouse_Event added.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "globals.h"

// Note:  random() generates from -32767 to 32767
// From it we make two generators, one for positive ints
// The other for positive floats.  There is also a C function,
// that could have been used.

// Generate random positive int in a range:
int ran_pos_int(int low, int high)
	{return (low + (32767 + rand()) % (high - low + 1));}

// Generate random positive float in range (inclusive).
int ran_pos_float(float low, float high)
	{return(low + (32767 + rand())/float(65534) * (high - low));}

// Is true the moment TickCount() equals or exceeds end_time
// Since TickCount() counts real time intervals (1/60's of a second) some absolute
// pace can be set, which won't vary from one machine to the next.
bool Time_Is_Up(unsigned long end_time)
	{return(TickCount() >= end_time);}

// Safe wait function fires the moment TickCount() equals or exceeds the time.
// It also notes mouse-down event -> mouse_was_down (global)
void Pause_Ticks(int nticks)
	{
	EventRecord	theEvent;
	unsigned long end_time = TickCount() + nticks;
	
	while(TRUE)
		{
		WaitNextEvent(everyEvent, &theEvent, 6, nil);
		 if(theEvent.what == mouseDown) mouse_was_down = TRUE;
		if (Time_Is_Up(end_time)) break; 
		}
	}

// This resets the mouse_was_down flag and then waits for a click
//  (it doesn't "save" earlier clicks).
bool Mouse_Event(int pause) 
	{
	mouse_was_down = FALSE;
	while(TRUE) 
		{Pause_Ticks(1); 
		if(mouse_was_down) return(TRUE);}}
		

/* 
	This function Copy_Win_Bits copies all the pixels from one window to another.
	Thus an object can be drawn in the left window and copied to the right,
	then erased and redrawn and then copied again.  No erased screen is ever
	seen in the right window, so animation can be smooth -- the updates from
	copying are so fast that no glitches are seen.

   This function is messy because of the complexity of its arguments.
   Here's the declaration from the TBA:
   
   void CopyBits (const BitMap *srcBits, const BitMap *dstBits,
							 const Rect *srcRect, const Rect *dstRect,
							 short mode, RgnHandle maskRgn);
	
	The primary task of building the arguments is to dig out the references
	from the various structures and to cast them to the right type, if necessary.
	CopyBits is explained functionally in IM Imaging, and the considerations for
	casting the args are best explained in the TBA (Toolbox Assistant). The major
	cast is to change the grafport from a color one to a basic QD grafport
	from which the bitmap is extracted.  The strong typing of C++ forces such casting. 						 
*/

void Copy_Win_Bits(Window_C *w1, Window_C *w2)
	{
	CopyBits(&GrafPtr(w1->win_ptr)->portBits, &GrafPtr(w2->win_ptr)->portBits,
				&w1->win_ptr->portRect, &w2->win_ptr->portRect, srcCopy, NULL);
	}
	
// Not clear that the cast here is required.	
void Clear_Window(Window_C *w)
	{EraseRect(&CGrafPtr(qd.thePort)->portRect);}



// *********************************************************
// END OF DEFINITIONS. NOW DEFINE FUNCTIONS TO RUN IN main()
// *********************************************************

/* 
File:	smoothy_fns.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	This defines globals (allocates and initializes), declared in globals.h.
				It also defines the functions that run in main().  These are the
				messiest functions in this project, since they have to deal with many
				details, both small and large.  Has both initialization routines and
				the routines that run/draw the examples, both geometrical objects and 
				text.
				

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.  A lot of "Lob" data structures were put
			in here initially but not subsequently. used.
7/29/98:	Project is now smoothy.  -- modest changes made.

*/

#include "globals.h"
#include "main.h"

bool mouse_was_down = FALSE;
int screen_w;
int screen_h;
int screen_mid;
int top_win;

Window_C *win_left;
Window_C *win_right;
Window_C *banner_win;
float x_min, x_max, y_min, y_max, vel_min, vel_max;
unsigned long startup_delay_max, run_time_max;
int ob_size;


void init_managers()
	{
	 InitGraf(&qd.thePort);	 
	 InitFonts();
	 InitWindows();
	 InitCursor();
	 TEInit();
	}

void init_globals()
	{
	mouse_was_down = FALSE;
	screen_w = qd.screenBits.bounds.right;
	screen_h = qd.screenBits.bounds.bottom;
	screen_mid = screen_w/2;
	top_win = screen_h/2;
	ob_size = 30;
	x_min = 2*ob_size;
	x_max = 0.8*screen_mid;
	y_min = 2*ob_size;
	y_max = 0.8*top_win;
	vel_min = 1.0;
	vel_max = 10.0;
	startup_delay_max = 30;
	run_time_max = 100;
	qd.randSeed = TickCount();
	
	}
	
void init_windows()
	{
	Point p;
	
	// create the left window (it flickers, bitblt *from* it)
	p.h = 3;	p.v = top_win;
	win_left = new Window_C(p, screen_mid - 6, top_win - 3);
	
	// And the right one (it's smooth, bitblt *to* it)
	p.h = screen_mid; p.v = top_win;
	win_right = new Window_C(p, screen_mid - 6, top_win - 3);
	}

// Puts initial Banner in left window:

void Banner_()
	{
	win_left->In_Window();	// set to draw in left window
	MoveTo(20,40);
	TextSize(24);
	DrawString("\pClick your way through this demo");
	Mouse_Event();
	}

// Ditto for another text piece, but 36pt type.  Window is cleared first.

void All_Done()
	{
	win_left->In_Window();	// set to draw in left window
	Clear_Window(win_left);
	MoveTo(20,60);
	TextSize(36);
	DrawString("\pAll Done!");
	}

// Moves circle across left window and bitblts to right window
void Move_circle_simple() 
	{
	Circle *circ = new Circle(100);
	Point pc; pc.h = 100; pc.v = 200;
	RGBColor c; c.red = 0xFFFF; c.green = 0; c.blue = 0; // a red
	
	win_left->In_Window();	// set to draw in left window
	RGBForeColor(&c);	// now that we're there, set forecolor
	
	// This loops, incrementing the horizontal position, via pc.h += 1.
	// For each position it sets the rectangle (square) describing the circle,
	// draws it, copies left window to right, pauses (0 for now), erases the
	// circle and then loops. The erased screen is never copied over == no flicker.
	for(int j = 0; j < 50; j++)
		{
		pc.h += 4;
		circ->Set_Origin_Rect(pc);
		circ->Draw();
		Copy_Win_Bits(win_left, win_right);
		// Pause_Ticks(0);
		circ->Erase();
		};
	}
	
// Draw a stationary polygon (and copybits).  This shows one way of drawing a polygon,
// not completely hidden inside the object as a member function.  This is the close to
// the underlying method used in QD: Open a polygon data structure, move to a point, 
// draw a series of lines and close the data structure.  We could easily implement an
// alernative form in which an array of points or x,y coordinates was created and passed.
// The Polygon data structure on the Mac allocates an array of exactly the right size,
// once it knows how many vertices there are, on closing the drawing sequence.
void Draw_One_Poly()
	{
	Poly *poly = NULL;
	RGBColor c; 
		c.red = 0; c.green = 0xFFFF; c.blue = 0x7FFF; // light green

	win_left->In_Window();	// set to draw in left window
	RGBForeColor(&c);	// now that we're there, set forecolor

	// Construct a triangle.  This is the
	poly->Open_Poly();
	MoveTo(100,100);
	LineTo(175, 135);
	LineTo(125, 250);
	poly->Close_Poly();
	
	// Draw it
	poly->Draw();
	Copy_Win_Bits(win_left, win_right);
	Pause_Ticks(60);
	poly->Erase();	// erase left but right remains
	Pause_Ticks(60);

	poly->Dispose_Poly();	// dispose/return the low-level data structure
	}
	
// Spin a line using 2D matrix transforms.  This involves concepts that come fairly
// early in our graphics course.  This uses rather simple vector and matrix classes
// and operations for now.  Remember that angles are in radians, about 6 radians around
// a circle (2*pi to be exact).  A radian is about 57 degrees.  But radians are especially
// good for describing small rotations, since rotating by 1/100 of a radian moves the end
// of a line about 1/100 of its length. The move/copy/pause/erase/update strategy is
// explained below.
  
void Spin_Line()
	{
	RGBColor c; 
	c.red = 0xFFFF; c.green = 0x1000; c.blue = 0x1000; // light red
	
	// xc,yc are the non-moving center points or the rotation, one end of the line.
	// xs,ys define the other end, which is constantly changed to "spin" the line.
	float xc = 150.0, yc= 150.0, xs = 200.0, ys = 200.0;
	
	Matrix_s  *m1 = new Matrix_s(-0.05, xc, yc);	//   1/20 radian each step
	Vector_s *v1 = new Vector_s(xs, ys);			//  holds the moving endpoint.				


	win_left->In_Window();	// set to draw in left window
	RGBForeColor(&c);	// now that we're there, set forecolor
	PenSize(1,30);	// make the pen really odd-shaped, giving "3D" effect.
	
	Line_  *line = new Line_(xc, yc, xs, ys);
	
	// Loop strategy is: xfer the vec values to the line, draw, bitblt, erase, loop.
	for(int i = 0; i < 100; i++)
		{
		line->Set_Line(xc, yc, 							// xfer vec to line
			int(v1->vec[0]), int(v1->vec[1]));	
		line->Draw();									// draw the line
		Copy_Win_Bits(win_left, win_right);  			// copy to right window
		// Pause_Ticks(1);									// pause 1/60 sec
		line->Erase();									// erase on the left
		Matrix_x_Vector(m1, v1);						// update v1 by slight rotation
		}
	}
	

// *******************************************************
// BELOW IS main.cp CONTAINING THE MAIN PROGRAM main()
// *******************************************************
	
/* 
File:	main.cp
Author:	R. P. Futrelle
Date:	7/29/98
Notice:	Copyright 1998 by R. P. Futrelle and the College of Computer Science,
		Northeastern University
Proj:	Code Warrior Mac project, smoothy.
Description:	This contains main() which consists of a handful of calls to routines
				defined in smoothy_fns.cp.  

Modification history:
1/12/98:	RPF. Started as console1 to use SIOUX
1/20/98:	RPF. Put in bitblt for simple circle motion 
 			and saved as "one smooth circle 1-98".
1/21/98:	lobs. project initiated.
1/25/98:	Many slight changes yesterday and today as things were tested.
			As of today the following things work, all bitblt'd from left window
			to right to give smooth motion:  moving circle, fixed triangle,
			line rotating around one end.  It also has various timed delays as well
			as mouse clicks between "scenes". (The triangle is an example that shows
			how to create and render polygons.)	
7/29/98:	Project is now smoothy.  -- modest changes made.
		`	Prepared for COM1370 class, summer 1998.



There are occasional references to the "TBA" which is the Toolbox Assistant,
a hyperlinked utility giving you call arguments for all the Toolbox calls
in easy-to-use cut-and-paste form (C code).  "IM" is Inside Macintosh, with
some references to the Toolbox volume and some to the Imaging volume. 

This project also demonstrates how to organize a large number of files
including declarations, definitions, globals, and main() in a consistent
way that can grow easily and safely, or be adapted to other projects.
				
The dependency chain has various branches, but is basically as follows
(illustrated for the graphics classes):

Forward references (bare declares) in:	graphics_classes_declares.h

Definitions of classes in:				graphics_classes.h

Definitions of member functions in:		graphics.cp

Ditto for other classes:				windows, linear_alg

All the headers are included in:		declarations.h
	except globals.h and main.h

Globals includes declarations:			globals.h
  and defines global vars.
  all .cp files include globals.h
  
General items with no other home:		utils.h and utils.cp

Functions in main() declared in:		main.h

Definitions of the main() functions:	smoothy_fns.pc

main() itself in:						main.cp
*/

#include "globals.h"
#include "main.h"


void main()
	{
	init_managers();
	
	init_globals();
	
	init_windows();
	
	Banner_();	// Tells user to click through the demo.
	
	// Moves circle across left window and bitblts to right
	Move_circle_simple();
	
	// Requires a click (mouse down) after this begins to execute,
	// before it will return and allow things to proceed.
	Mouse_Event();	
	
	// Draw a simple polygon
	Draw_One_Poly();
	
	// ditto
	Mouse_Event();
	
	// Spin a line using 2D (3x3) rotation matrix
	Spin_Line();
	
	// Announce all done
	All_Done();

	// This returns when the mouse event occurs -- another way to use it.
	if(Mouse_Event(1)) return;	// to quit entire run, when done
	
	}