Plotting complex i using OpenGL

Since complex numbers is 3 dimensional room merged into an equation. We're going to plot it using OpenGL. This small project consists of these basic files:

screenshot

nvvirt.c

In this file we do basic glut initialization. Further we specify the projection mode.

#include <GL/glut.h>

#include "nvvirt_draw.h"
#include "nvvirt_plot.h"

void init();
void display_delegate();
void reshape_delegate(int w, int h);
void mouse_delegate(int button, int state, int x, int y);
void keyboard_delegate(unsigned char key, int x, int y);

void
init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glShadeModel(GL_FLAT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluPerspective(100.0, 1.0, -1000.0, 1000.0);
  gluLookAt(2000.0, 100.0, 2000.0,
	    0.0, 1100.0, 0.0,
	    0.0, 1.0, 0.0);
}

void
display_delegate()
{
  double **plot_v3f;
  unsigned long plot_length;
  unsigned int i;

  glClear(GL_COLOR_BUFFER_BIT);

  nvvirt_draw_main(1000.0,
		   50.0, 12.5,
		   NVVIRT_DRAW_MAIN_AXIS |
		   NVVIRT_DRAW_MAIN_SCALE);

  plot_length = 18;
  plot_v3f = nvvirt_plot_i(plot_length);
  glColor3f(0.0, 0.0, 1.0);

  glPushMatrix();
  glBegin(GL_LINE_STRIP);

  for(i = 0; i < plot_length; i++){
    glVertex3f(plot_v3f[i][0], plot_v3f[i][1], plot_v3f[i][2]);
  }

  glEnd();

  glPopMatrix();
  glFlush();
  glFinish();

  glutSwapBuffers();
}

void
reshape_delegate(int w, int h)
{
  display_delegate();
}

void
mouse_delegate(int button, int state, int x, int y)
{
  int viewport[4];
  double mvmatrix[16];
  double projmatrix[16];
  int realy;
  double wx, wy, wz;
  static int old_x = 0, old_y = 0, old_z = 0;

  switch(button){
  case GLUT_LEFT_BUTTON:
    {
      glGetIntegerv(GL_VIEWPORT, viewport);
      glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
      glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);

      display_delegate();
    }
    break;
  case GLUT_RIGHT_BUTTON:
    {
    }
    break;

  }

  old_x = x;
  old_y = y;
}

void
keyboard_delegate(unsigned char key, int x, int y)
{
}

int
main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize(1600, 1600);
  glutInitWindowPosition(100, 100);

  glutCreateWindow("libVirt\0");

  init();

  glutDisplayFunc(display_delegate);
  glutReshapeFunc(reshape_delegate);
  glutMouseFunc(mouse_delegate);

  glutMainLoop();

  return(0);
}

nvvirt_draw.h

Here we declare our drawing function.


#ifndef __NVVIRT_DRAW_H__
#define __NVVIRT_DRAW_H__

typedef enum{
  NVVIRT_DRAW_MAIN_AXIS      = 1,
  NVVIRT_DRAW_MAIN_SCALE     = 1 << 1,
}NVVIRT_DRAW_MAIN_FLAGS;

void nvvirt_draw_main(double length, double lower, double upper, unsigned int flags);

#endif /*__NVVIRT_DRAW_H__*/

nvvirt_draw.c

For usability we draw a 3D coordinate's system.

#include "nvvirt_draw.h"

#include <GL/glut.h>

#define NVVIRT_DRAW_MAIN_MARKER_X(x) glBegin(GL_LINES);			\
  glVertex3f(x - (scale_length / 2.0), 0.0, 0.0);			\
  glVertex3f(x + (scale_length / 2.0), 0.0, 0.0);			\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(x, -1.0 * (scale_length / 2.0), 0.0);			\
  glVertex3f(x, (scale_length / 2.0), 0.0);				\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(x, 0.0, -1.0 * (scale_length / 2.0));			\
  glVertex3f(x, 0.0, (scale_length / 2.0));				\
  glEnd();								

#define NVVIRT_DRAW_MAIN_MARKER_Y(y) glBegin(GL_LINES);			\
  glVertex3f(-1.0 * (scale_length / 2.0), y, 0.0);			\
  glVertex3f((scale_length / 2.0), y, 0.0);				\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(0.0, y - (scale_length / 2.0), 0.0);			\
  glVertex3f(0.0, y + (scale_length / 2.0), 0.0);			\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(0.0, y, -1.0 * (scale_length / 2.0));			\
  glVertex3f(0.0, y, (scale_length / 2.0));				\
  glEnd();

#define NVVIRT_DRAW_MAIN_MARKER_Z(z) glBegin(GL_LINES);			\
  glVertex3f(-1.0 * (scale_length / 2.0), 0.0, z);			\
  glVertex3f((scale_length / 2.0), 0.0, z);				\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(0.0, -1.0 * (scale_length / 2.0), z);			\
  glVertex3f(0.0, (scale_length / 2.0), z);				\
  glEnd();								\
  glBegin(GL_LINES);							\
  glVertex3f(0.0, 0.0, z - (scale_length / 2.0));			\
  glVertex3f(0.0, 0.0, z + (scale_length / 2.0));			\
  glEnd();

void
nvvirt_draw_main(double length, double lower, double upper, unsigned int flags)
{
  double large_scale_step, small_scale_step;
  double scale_step;
  unsigned int large_i_stop, small_i_stop;
  unsigned int i, i_stop;

  /* draw main axis */
  if((NVVIRT_DRAW_MAIN_AXIS & flags) != 0){
    glClear(GL_COLOR_BUFFER_BIT |
            GL_STENCIL_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glLineWidth(1.3);

    glPushMatrix();

    glBegin(GL_LINES);
    glVertex3f(-1.0, 0.0, 0.0);
    glVertex3f(1.0, 0.0, 0.0);
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(0.0, -1.0, 0.0);
    glVertex3f(0.0, 1.0, 0.0);
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(0.0, 0.0, -1.0);
    glVertex3f(0.0, 0.0, 1.0);
    glEnd();

    glPopMatrix();
    glFlush();
  }

  /* draw scale */
  if(lower <= 0.0){
    return;
  }

  if(upper <= 0.0){
    return;
  }

  if((NVVIRT_DRAW_MAIN_SCALE & flags) != 0){
    large_scale_step = length / upper;
    small_scale_step = length / lower;

    large_i_stop = length / large_scale_step;
    small_i_stop = length / small_scale_step;

    glClear(GL_STENCIL_BUFFER_BIT);
    glLineWidth(1.0);

    /* x */
    i_stop = large_i_stop;
    scale_step = large_scale_step;

    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_X((length / 2.0) - (i * scale_step));
    }

    glScalef(2.5, 2.5, 2.5);

    glPopMatrix();
    glFlush();

    i_stop = small_i_stop;
    scale_step = small_scale_step;

    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_X((length / 2.0) - (i * scale_step));
    }

    glPopMatrix();
    glFlush();

    /* y */
    i_stop = large_i_stop;
    scale_step = large_scale_step;

    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_Y((length / 2.0) - (i * scale_step));
    }

    glScalef(2.5, 2.5, 2.5);
    glPopMatrix();

    i_stop = small_i_stop;
    scale_step = small_scale_step;
    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_Y((length / 2.0) - (i * scale_step));
    }

    glPopMatrix();
    glFlush();

    /* z */
    i_stop = large_i_stop;
    scale_step = large_scale_step;

    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_Z((length / 2.0) - (i * scale_step));
    }

    glScalef(2.5, 2.5, 2.5);
    glPopMatrix();

    i_stop = small_i_stop;
    scale_step = small_scale_step;
    glPushMatrix();

    for(i = 0; i < i_stop; i++){
      NVVIRT_DRAW_MAIN_MARKER_Z((length / 2.0) - (i * scale_step));
    }

    glPopMatrix();
    glFlush();
    glFinish();
  }
}

nvvirt_plot.h

Here we declare our plotting function.

#ifndef __NVVIRT_PLOT_H__
#define __NVVIRT_PLOT_H__

#define NVVIRT_PLOT_DEFAULT_LENGTH (8192)

double** nvvirt_plot_i(unsigned int length);

#endif /*__NVVIRT_PLOT_H__*/

nvvirt_plot.c

Here we do finally the plot of complex i.

#include "nvvirt_plot.h"

#include <math.h>
#include <stdlib.h>

void
nvvirt_plot_i(unsigned int length)
{
  double **plot_v3f;
  double azimut;
  unsigned int i, j;

  plot_v3f = (double**) malloc(length * sizeof(double*));

  for(i = 0; i < length / 2.0; i++){
    plot_v3f[i] = (double *) malloc(3 * sizeof(double));

    azimut = -1.0 * sin((length / 2.0) * (2.0 * M_PI) / ((double) i) / 4.0);

    plot_v3f[i][0] = -1.0 * azimut;
    plot_v3f[i][1] = azimut;
    plot_v3f[i][2] = azimut;
  }

  for(j = 0; i < length; i++, j++){
    plot_v3f[i] = (double *) malloc(3 * sizeof(double));

    plot_v3f[i][0] = -1.0 * exp((1.0 / 3.0) * log((double) j));
    plot_v3f[i][1] = exp(3.0 * log((double) j));
    plot_v3f[i][2] = (double) j;
  }
  
  return(plot_v3f);
}