/* This program draw orbits of points in the Mandelbrot Set.  The right
mouse button display the coordinates in the Complex Plane, the left mouse 
button will draw the orbit, and the middle mouse button erases the screen 
so that you can draw again.
*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include <GL/glut.h>

#define initial_width 600
#define initial_height 600
#define max_colors 10

int main_window;

// The following code permits drawing text on the screen 
// Bitmap character fonts must be pre-defined

float colarry[max_colors][3] = {{1.0, 0.0, 0.0}, {0.0, 0.8, 0.0}, 
                                {0.0, 0.0, 0.8}, {0.8, 0.0, 0.8},
                                {0.8, 0.5, 0.0}, {0.0, 0.8, 0.8},
                                {1.0, 0.0, 0.5}, {0.0, 0.8, 0.3},
                                {0.4, 0.4, 1.0}, {0.0, 0.0, 0.0} };

void bitmap_output(int x, int y, int z, char *string, void *font)
{
  int len, i;

  glRasterPos3f(x, y, 0);
  len = (int) strlen(string);
  for (i = 0; i < len; i++) {
    glutBitmapCharacter(font, string[i]);
  }
}



void DrawAxes()
{float x;
 int i= 0;
 char str[15];
 glColor3f(0.6, 0.6, 0.6);
 glBegin(GL_LINES);
  glVertex3f(-1.9,0.0,0.0);  // Draw the main axes
  glVertex3f(1.9,0.0,0.0);
  glVertex3f(0.0, -1.9,0.0);
  glVertex3f(0.0, 1.9,0.0);
  x = -1.90;
  while( x < 2.0) {        // Draw the little notches on the axes
    glVertex3f(x, -0.01, 0.0); 
    glVertex3f(x, 0.01, 0.0); 
    glVertex3f(-0.01, x, 0.0); 
    glVertex3f(0.01, x, 0.0); 
    x += 0.1;
   }
 glEnd();
 x = -1.0;
 while( x < 2.0) {   // Put numbers on the axes at integer spots
    if (x != 0.0) {
       sprintf(str,"%3.1f ",x);  
       glPushMatrix();
         glTranslatef(x - 0.05, -0.07, 0.0);
         bitmap_output(0,0,0, str, GLUT_BITMAP_TIMES_ROMAN_10);
       glPopMatrix();
       glPushMatrix();
         glTranslatef( 0.02, x ,  0.0);
         bitmap_output(0,0,0, str, GLUT_BITMAP_TIMES_ROMAN_10);
       glPopMatrix();
     }
    x += 1.0;

   }

}

void DrawMandel(void)     // This routine draws an image of the Mandelbrot Set
 {float x0,y0,xn,yn,xtemp, xstep, ystep;
  float x,y;
  static char s1[25], s2[25];
  int iter;
   xstep =  0.01;
   ystep =  0.01;


//   xstep =  4.0/(600.0);
//   ystep =  4.0/(600.0);
   glBegin(GL_POINTS);
   for (y = -2.0; y <= 2.0; y += ystep) {
      for (x = -2.0; x <= 2.0; x += xstep)  {
        iter=0;
        x0 = x;
        y0 = y;
        xn= x0;
        yn= y0;
        while(iter<20 && (xn*xn +yn*yn <4.0)) {
          xtemp = xn*xn - yn*yn +x0;
          yn = 2*xn*yn + y0;
          xn = xtemp;
          iter++;
         }
        if (iter >= 20) {
          glColor3f(0.8, 0.8, 0.8);
          }
        else
          glColor3f(1.0, 1.0, 0.7);
       glVertex3f(x, y, 0.0);
       }
     }     
    glEnd();
}

void mouse1(int button, int state, int x, int y)
{ float x0,y0,xn,yn,xtemp;
  static char s1[25], s2[25];
  int i;
  static int num = 0;
  if ( button== 0 && state == GLUT_DOWN)
   {x0 = -2.0 + x/(600.0/4);
    y0 = 2.0 - y/(600.0/4);
    glColor3f( colarry[num][0], colarry[num][1], colarry[num][2]);
    num++;
    if (num>= max_colors) num=0;
    printf ("%d %d  %f %f \n",x,y,x0,y0);
    glBegin(GL_LINE_STRIP);
    i=0;
    xn= x0;
    yn=y0;
    glVertex3f(xn,yn,0.0);
    while(i<100 && (xn*xn +yn*yn <4.0))  
      {xtemp = xn*xn - yn*yn +x0;
       yn = 2*xn*yn + y0;
       xn = xtemp;
       glVertex3f(xn,yn,0.0);
       i++;
      } 
      printf("\n");

    glEnd();
   }


  if ( (button== 2 || button== 0 )&& state == GLUT_DOWN)
    {x0 = -2.0 + x/(600.0/4);
     y0 = 2.0 - y/(600.0/4);
     sprintf (s2," ( %f, %fi )\0",x0,y0);
     glPushMatrix();
       glColor3f(1.0,1.0,0.7);
       glTranslatef(0.1, 1.85, 0);
       bitmap_output(0,0,0, s1, GLUT_BITMAP_TIMES_ROMAN_24);
       glColor3f(0.0,0.0,0.6);
       bitmap_output(0,0,0, s2, GLUT_BITMAP_TIMES_ROMAN_24);
       for(i=0; i<25; i++) {s1[i] = s2[i]; }
     glPopMatrix();
    }



  if ( button== 1 && state == GLUT_DOWN)
   {glClearColor(1.0, 1.0, 0.7, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    DrawMandel();
    DrawAxes();
   }

}



  
// Main display window 

void display(void)
{ glClearColor(1.0, 1.0, 0.7, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();
  glOrtho(-2.0, 2.0, -2.0, 2.0, -1.0, 1.0);
  DrawMandel();
  DrawAxes();
  glFlush();
}
  				


int main(int argc, char **argv)
{ 
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB);
  glutInitWindowSize(initial_width, initial_height);
  main_window = glutCreateWindow("Mandelbrot Orbits ");
  glutDisplayFunc(display);
  glutMouseFunc(mouse1);

  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}
