/*
	The dragon curve in 2D.
   
	Source file to be used with
	Cunningham, Computer Graphics: Programming in OpenGL for Visual Communication, Prentice-Hall, 2007

	Intended for class use only
*/
#include <GLUT/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define XMIN -3.
#define XMAX 3.
#define YMIN -3.
#define YMAX 3.
#define WS 700
#define NMAX 10

float sqrt2;
typedef float point2[2];

void myinit(void)
{ 
    glClearColor(.25, .25, .25, 1.);
	glLineWidth(2.);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	gluOrtho2D(XMIN,XMAX,YMIN,YMAX);
	
	sqrt2 = sqrt(2.);	
}

void lineThreePoints(point2 A, point2 B, point2 C, int n)
{
	point2 D;
	float x, y;
	
	if (n >= NMAX) {
		glBegin(GL_LINE_STRIP);
			glVertex2fv(A);
			glVertex2fv(B);
			glVertex2fv(C);
		glEnd();
	}
	else {
		x = B[0]-A[0]; y = B[1]-A[1];
		D[0] = A[0] + (x-y)/(sqrt2*sqrt2); //.5*(x-y)/sqrt2;
		D[1] = A[1] + (x+y)/(sqrt2*sqrt2); //.5*(x+y)/sqrt2;
		lineThreePoints(A, D, B, n+1);
		x = C[0]-B[0]; y = C[1]-B[1];
		D[0] = B[0] + (x+y)/(sqrt2*sqrt2); //.5*(x+y)/sqrt2;
		D[1] = B[1] + (y-x)/(sqrt2*sqrt2); //.5*(y-x)/sqrt2;
		lineThreePoints(B, D, C, n+1);
	}
}

void lineTwoPoints(point2 P1, point2 P2, int n)
{
	point2 P3;
	float x, y;

	x = P2[0]-P1[0]; y = P2[1]-P1[1];
	P3[0] = P1[0] + (x-y)/(sqrt2*sqrt2);
	P3[1] = P1[1] + (x+y)/(sqrt2*sqrt2);
	lineThreePoints(P1, P3, P2, n+1);
}

void display( void )
{
	point2 A0 = {0., 0.}, A1 = { 2., 0.};
	point2 B0 = {0., 0.}, B1 = { 0., 2.};
	point2 C0 = {0., 0.}, C1 = {-2., 0.};
	point2 D0 = {0., 0.}, D1 = { 0.,-2.};
	
	glClear(GL_COLOR_BUFFER_BIT);
	
	glColor3f(0.,0.,0.);
	lineTwoPoints(A0, A1, 0);
	glColor3f(1., .6, .5);
	lineTwoPoints(B0, B1, 0);
	glColor3f(0.,1.,0.);
	lineTwoPoints(C0, C1, 0);
	glColor3f(1.,1.,1.);
	lineTwoPoints(D0, D1, 0);
    glutSwapBuffers();
 }

void reshape(int w,int h)
{
        glViewport(0,0,(GLsizei)w,(GLsizei)h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
//		gluOrtho2D(0.,2.,-1.,1.);
		gluOrtho2D(-3.,3.,-3.,3.);
}

int main(int argc, char** argv)
{
/* Standard GLUT initialization */
	glutInit(&argc,argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(WS,WS);
	glutInitWindowPosition(50,50);
	glutCreateWindow("Dragon curve IFS");
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);

	myinit();

	glutMainLoop();
}