// julia - Hip - 2009-12-20
// Julia-ovi skupovi (Julia sets) - granice podruccja
// konvergencije za funkciju
//         f(z) = lambda * z * (1 - z)
// najzanimljivije je podruccje 2.0 < lambda < 4.0
// (opchenito, lambda mozhe biti i kompleksan)
// 'l' - smanjuje lambda
// 'L' - povechava lambda

#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

double lambda = 2.0; // parametar
int npoints = 100000; // broj toccaka
int sign = 1;

typedef struct { double x; double y; } complex;

complex iteriraj(double lambda, complex z) {
double rz, iz, az;
complex zz;

  rz = 1.0 - 4.0 * z.x / lambda;
  iz = -4.0 * z.y / lambda;
  az = sqrt(rz * rz + iz * iz);

  if(rand() < RAND_MAX / 2) sign = 1; else sign = -1;  
  zz.x = (1.0 + sign * sqrt((az + rz) / 2.0)) / 2.0;
  if(iz < 0.0) sign = -sign;
  zz.y = sign * sqrt((az - rz) / 2.0) / 2.0;

  return zz;
} // iteriraj

void iscrtaj(void) {
  complex z = {0.7, 0.1};
  int i;

  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslated(-0.5, 0.0, 0.0);

  // nekoliko praznih iteracija
  for(i = 0; i < 100; i++)
    z = iteriraj(lambda, z);

  glColor3f(1.0, 1.0, 0.0);
  for(i = 0; i < npoints; i++) {
    z = iteriraj(lambda, z);
    glBegin(GL_POINTS);
      glVertex2d(z.x, z.y);
    glEnd();
  }

  glutSwapBuffers();
} // iscrtaj

void skaliraj(int w, int h) {
  float a = 0.5, b;

  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if(w > h) {
    b = a * (float)w / (float)h;
    glOrtho(-b, b, -a, a, -a, a);
  } else {
    b = a * (float)h / (float)w;
    glOrtho(-a, a, -b, b, -a, a);
  }
} // skaliraj

void tipka(unsigned char c, int x, int y) {
  if(c == 'q') exit(0);
  if(c == 'l') { lambda -= 0.01; }
  if(c == 'L') { lambda += 0.01; }
  printf("lambda = %lf\n", lambda);
  glutPostRedisplay();
} // tipka

int main(int argc, char** argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize(640, 480);
  glutInitWindowPosition(0, 0);
  glutCreateWindow(argv[0]);

  glClearColor(0.0, 0.0, 0.0, 0.0);

  glutDisplayFunc(iscrtaj);
  glutReshapeFunc(skaliraj);
  glutKeyboardFunc(tipka);

  glutMainLoop();
  return 0;
} // main

