/* NIGHTFALL OpenGL Interface                                              */
/* Copyright (C) 2001 Rainer Wichmann & Markus Kuster                      */
/*                                                                         */
/*  This program is free software; you can redistribute it                 */
/*  and/or modify                                                          */
/*  it under the terms of the GNU General Public License as                */
/*  published by                                                           */
/*  the Free Software Foundation; either version 2 of the License, or      */
/*  (at your option) any later version.                                    */
/*         
                                                                */
/*  This program is distributed in the hope that it will be useful,        */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*  GNU General Public License for more details.                           */
/*                                                                         */
/*  You should have received a copy of the GNU General Public License      */
/*  along with this program; if not, write to the Free Software            */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */

/* ANSI C forbids an empty source file, so put this outside                */
/* do nothing here if we don't have OpenGL                                 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Light.h"

#ifdef  _WITH_OPENGL
#include "LightGLPrefs.h"


/******************************************************************
 @package   nightfall
 @author    Rainer Wichmann (rwichman@lsw.uni-heidelberg.de)
 @version   1.3
 @short     The color wedge code 
 @param     (int)  Comp the component
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLDisplayWedge( int Comp )
{
  float maxval = texture_maxval[Comp];
  float minval = texture_minval[Comp];
  char  label[128];

  /* plot borders
   */
  float xmin   =  -0.5;
  float lmin   =  -0.9;
  float xmax   =  0.5;
  float ymin   = -0.5;
  float ymax   =  0.5;

  double        ScaleMass;          /* units conversion              */
  double G_SI  = 6.6726e-11;        /* gravitational constant        */
  char   texwhat[16];

  struct GLColorSystem NTSC = {0.64, 0.33, 0.29, 0.60, 0.15, 0.06, CWP}; 
  struct GLColorSystem *cs; 
  double  x, y, z, R, G, B, max;
  
  /* R.W. 23.12.2002 set colours to BB colour
   */
  cs     = &NTSC;
  GLBBtoxyz(Binary[Comp].Temperature, &x, &y, &z);
  GLxyztoRGB(cs, x, y, z, &R, &G, &B);
  max = (R > G) ? R : G;
  max = (B > max) ? B : max;
  R = (1.0 / max) * R;
  G = (1.0 / max) * G;
  B = (1.0 / max) * B;

  if (Flags.textype == TEMP)
    {
      strcpy(texwhat, "Kelvin");
    }
  else if (Flags.textype == GRAV)
    {
      ScaleMass = Binary[Primary].Mq / ( 1.0 + Binary[Primary].Mq);
      minval = minval * Orbit.TrueMass * (1.0 - ScaleMass)
	* G_SI
	/ (Orbit.TrueDistance * Orbit.TrueDistance);
      maxval = maxval * Orbit.TrueMass * (1.0 - ScaleMass)
	* G_SI
	/ (Orbit.TrueDistance * Orbit.TrueDistance);
      strcpy(texwhat, "m kg/s^2");
    }
  else if (Flags.textype == FLUX)
    {
      minval = (1.0 / maxval) * minval;
      maxval = 1.0;
      strcpy(texwhat, "relative flux");
    }
  else if (Flags.textype == VELOCITY)
    {
      strcpy(texwhat, "m/s");
    }
  else
    {
      strcpy(texwhat, "?");
    }


  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      /* disable lighting, we don't want ligthing with */
      /* the axes                                      */
      glDisable(GL_LIGHTING);

      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(-1, 1, -1, 1, -1, 1);
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

      /* draw border for plot                                              */
      glBegin(GL_QUADS); 
      glColor3f(0.0, 0.0, 0.0);
      glVertex3f(xmin, ymin, 0.0);
      glVertex3f(xmin, ymax, 0.0);
      glColor3f(R, G, B); 
      glVertex3f(xmax, ymax, 0.0);
      glVertex3f(xmax, ymin, 0.0);
      glEnd(); 
      glPopMatrix();

#if 0
      /* draw  tickmarks                                                   */
      glBegin(GL_LINES); 
      glVertex2f(-0.5, bot_xtick);       
      glVertex2f(-0.5, top_xtick);       
      glVertex2f( 0.0, bot_xtick);       
      glVertex2f( 0.0, top_xtick);       
      glVertex2f( 0.5, bot_xtick);       
      glVertex2f( 0.5, top_xtick);
      glVertex2f( 1.0, bot_xtick);
      glVertex2f( 1.0, top_xtick);
      glEnd();
#endif

      /* select font                                   */
      GLSetFont(HELVETICA, 12);

      glDisable(GL_LIGHTING);
      
      glPushMatrix();

      /* print labels                                  */
      glColor3f(1.0, 1.0, 1.0);
      snprintf(label,  127, "%c: %10.4g",
	       (Comp == Primary) ? 'P' : 
	       (Comp == Secondary) ? 'S' : 'D', minval);
      GLDrawStr(lmin, -0.2,      0.0, label);
      snprintf(label,  127, "%10.4g (%s)", maxval, texwhat);
      GLDrawStr(xmax, -0.2,      0.0, label);

#if 0
      /* print tick marks                              */
      GLDrawStr(-0.545,bot_xtick-0.1*length_y,0.0,"0.5");
      GLDrawStr(-0.05,bot_xtick-0.1*length_y,0.0,"0.0");
      GLDrawStr( 0.455,bot_xtick-0.1*length_y,0.0,"0.5");
      GLDrawStr( 0.96,bot_xtick-0.1*length_y,0.0,"1.0");

      /* print title string                            */
      glColor3f(1.0, 1.0, 1.0);
      GLDrawStr(coord.titlepos,yaxis.max_value+0.15*length_y,0.0,coord.title);
#endif
      glPopMatrix();

      /* switch on lighing                             */
      glEnable(GL_LIGHTING);
      
      /* set line width to 1                           */
      glLineWidth(1);
    }
}


/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   0.5
 @short     The main 3D window rendering code 
 @param     (GtkWidget)  *widget  discarded
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLDisplay3d( GtkWidget *widget )
{
  float  com;                         /* center of mass          */

  GLfloat m[4][4],h;
  OrbitType  *OrbPtr = &Orbit;  /* pointer to Orbit               */
  DispInfo *DispInfoPtr;

  struct GLColorSystem NTSC = {0.64, 0.33, 0.29, 0.60, 0.15, 0.06, CWP}; 
  struct GLColorSystem *cs; 
  double  x, y, z, R, G, B, max;
  
  /* R.W. 23.12.2002 set colours to BB colour
   */
  cs     = &NTSC;
  GLBBtoxyz(Binary[Primary].Temperature, &x, &y, &z);
  GLxyztoRGB(cs, x, y, z, &R, &G, &B);
  max = (R > G) ? R : G;
  max = (B > max) ? B : max;
  primary_colour[0] = (1.0 / max) * R;
  primary_colour[1] = (1.0 / max) * G;
  primary_colour[2] = (1.0 / max) * B;

  cs     = &NTSC;
  GLBBtoxyz(Binary[Secondary].Temperature, &x, &y, &z);
  GLxyztoRGB(cs, x, y, z, &R, &G, &B);
  max = (R > G) ? R : G;
  max = (B > max) ? B : max;
  secondary_colour[0] = (1.0 / max) * R;
  secondary_colour[1] = (1.0 / max) * G;
  secondary_colour[2] = (1.0 / max) * B;

#ifdef HAVE_DISK
  cs     = &NTSC;
  GLBBtoxyz(Binary[Disk].Temperature, &x, &y, &z);
  GLxyztoRGB(cs, x, y, z, &R, &G, &B);
  max = (R > G) ? R : G;
  max = (B > max) ? B : max;
  disk_colour[0] = (1.0 / max) * R;
  disk_colour[1] = (1.0 / max) * G;
  disk_colour[2] = (1.0 / max) * B;
#endif

  DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
  /* get the dimension of the GTK window      */

  h= (GLfloat) glArea->allocation.height / (GLfloat) glArea->allocation.width;

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();

      glOrtho((-1 - DispInfoPtr->xpos)  * DispInfoPtr->zoom,
	      ( 1 - DispInfoPtr->xpos)  * DispInfoPtr->zoom,
	       -1 * DispInfoPtr->zoom,1 * DispInfoPtr->zoom,.1,1000.);

      glMatrixMode(GL_MODELVIEW);
      
      /* the x coordinate of the center of mass                      */
      com = (((float)(Binary[Primary].Mq))/( 1.0 + (float)(Binary[Primary].Mq)));

      /* load identity transformation matrix            */
      glLoadIdentity();

      /* set the drawing mode to polygon mode           */
      if (Flags.wireframe == ON) {
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
      } else {
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      }

      /* set view point position to (Flags.GLdistancex,0,Flags.GLdistancez)*/
      /* look to point              (Flags.GLdistancex,0,       0         )*/
      /* with head up pointing to   (        0        ,1,       0         )*/
      gluLookAt(Flags.GLdistancex,0,Flags.GLdistancez,Flags.GLdistancex,0,0,0,1,0);

      build_rotmatrix(m,DispInfoPtr->quat);
      glMultMatrixf(&m[0][0]);
      
      /* rotate orbit accoding to the inclination       */
      glRotated((270.0-((OrbPtr->Inclination-PI/2.0)*180.0/PI)),1,0,0);

      /* rotate phase steps                             */
      glRotated((OrbPtr->Phase-0.5*PI)*180.0/PI,0,0,1);
     
      glTranslatef(-(com),0.0,0.0);

      if (Flags.axes == ON) {
	/* draw x-,y- and z-axes                        */
	glPushMatrix();
	GLDrawAxes(0.4,glArea);
	glPopMatrix();
      }
      if (Flags.labels == ON) {
	glPushMatrix();
	GLDrawLabels(glArea);
	glPopMatrix();
      }

      /* save transformation matix                      */
      glPushMatrix();

      /* set the material options for primary           */
      /* primary emission; should be set according      */
      /* to the primary temperature                     */
      glMaterialfv(GL_FRONT, GL_EMISSION,  primary_colour);
      glMaterialfv(GL_FRONT, GL_DIFFUSE,   primary_mat_diffuse);
      glMaterialfv(GL_FRONT, GL_SPECULAR,  primary_mat_specular);
      glMaterialfv(GL_FRONT, GL_SHININESS, primary_mat_shininess);
      glFrontFace(GL_CCW);

      if ((Flags.texture == ON) && (Texture[Primary].IsOn == ON)) {
	/* enable texturing                                          */
	glEnable(GL_TEXTURE_2D);
	/* assign texture to the primary display list   */
	glBindTexture(GL_TEXTURE_2D, Texture[Primary].TexName);
	/* call primary lobe display list               */
	glCallList(PrimaryList);
	glBindTexture(GL_TEXTURE_2D, 0);
	/* switch off texturing                         */
	glDisable(GL_TEXTURE_2D);
      } else {
	/* call primary lobe display list               */
	glCallList(PrimaryList);
      }

      /* restore transformation matrix                  */
      glPopMatrix();
      
      /* save transformation matrix                      */
      glPushMatrix();

      /* translate to the position of the secondary                */
      glTranslatef (1.0, 0.0, 0.0);

      /* set the material options for secondary         */
      glMaterialfv(GL_FRONT, GL_EMISSION, secondary_colour);
      glFrontFace(GL_CW);

      if ((Flags.texture == ON) && (Texture[Secondary].IsOn == ON)) {
	/* enable texturing                             */
	glEnable(GL_TEXTURE_2D);
	/* assign texture to the secondary display list */
	glBindTexture(GL_TEXTURE_2D, Texture[Secondary].TexName);
	/* call secondary lobe display list             */
	glCallList(SecondaryList);
	glBindTexture(GL_TEXTURE_2D, 0);
	/* switch off texturing                         */
	glDisable(GL_TEXTURE_2D);
      } else {
	/* call secondary lobe display list             */
	glCallList(SecondaryList);
      }
      glPopMatrix();
      
#ifdef HAVE_DISK
      glPushMatrix();
      /* set the material options for the disk          */
      /* primary emission; should be set according      */
      /* to the disk temperature                        */
      glMaterialfv(GL_FRONT, GL_EMISSION,  disk_colour);
      glMaterialfv(GL_FRONT, GL_DIFFUSE,   disk_mat_diffuse);
      glMaterialfv(GL_FRONT, GL_SPECULAR,  disk_mat_specular);
      glMaterialfv(GL_FRONT, GL_SHININESS, disk_mat_shininess);

      /* translate to the position of the secondary                */
      glTranslatef (1.0, 0.0, 0.0);
      /* rotate in opposite direction according to orbital motion  */
      glRotated(-(OrbPtr->Phase-0.5*PI)*180.0/PI,0,0,1);

      if (Flags.disk == ON ) {
	if ((Flags.texture == ON) && ( Texture[Disk].IsOn == ON)){
	  /* enable texturing                           */
	  glEnable(GL_TEXTURE_2D);
	  /* assign texture to the disk display list */
	  glBindTexture(GL_TEXTURE_2D, Texture[Disk].TexName);
	  /* call accretion disk display list           */
	  glCallList(DiskList);
	  glBindTexture(GL_TEXTURE_2D, 0);
	  /* switch off texturing                       */
	  glDisable(GL_TEXTURE_2D);
	} else {
	  glCallList(DiskList);
	}
      }
      /* restore transformation matrix                  */
      glPopMatrix();
#endif 

      glPushMatrix();
      /* set light positions                            */
      glLightfv(SCENE_LIGHT, GL_POSITION      , Lights[SCENE_LIGHT].Pos);
      glLightfv(DISK_SPOT  , GL_POSITION      , Lights[DISK_SPOT].Pos);      
      glLightfv(DISK_SPOT  , GL_SPOT_DIRECTION, Lights[DISK_SPOT].Direction);
      /*glLightfv(GL_LIGHT2, GL_POSITION, lightpos);*/
      /*glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, primary_spot2_direction);*/
      glPopMatrix();
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   0.5
 @short     The main light curve/rad. vel. rendering code 
 @param     (GtkWidget)  *widget  discarded
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLDisplayPlot( GtkWidget *widget, int type)
{
  AxisType xaxis;
  AxisType yaxis;
  
  xaxis = CoordSys[type].xaxis;
  yaxis = CoordSys[type].yaxis;

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      
      glOrtho(xaxis.min_value-0.1*xaxis.length, xaxis.max_value+0.1*xaxis.length, 
	      yaxis.min_value-0.3*yaxis.length, yaxis.max_value+0.2*yaxis.length,
	      -2.0,2.0); 
      
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();

      /* set the drawing mode to polygon mode           */
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

      /* Call plot list                                 */
      glCallList(PlotList[type]);
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   1.0
 @short     The light curve drawing code 
 @param     (void)
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLMakeLCPlot( void )
{
  double    Calib;                 /* normalization for flux         */
  int       i,test;
  float     *Xplot,*Yplot,Xtick;   /* x, y position                  */
  float     MinMag, MaxMag;        /* Min,Max scaling for plot       */
  PhotoOut  *FluxPtr = FluxOut;    /* pointer to flux                */
  int    js;                       /* j minus invalid                */

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      /* Initialize memory for plot                                  */
      Xplot = malloc(3 * MAXELEMENTS * sizeof(float)); 
      Yplot = malloc(3 * MAXELEMENTS * sizeof(float)); 
      
      if (Xplot == NULL || Yplot == NULL) 
#ifdef _WITH_GTK 
  	{  
	  if (Flags.interactive == ON) { 
  	    make_dialog (_(errmsg[0])); 
  	    if (Xplot != NULL) free(Xplot); 
  	    if (Yplot != NULL) free(Yplot); 
  	    return; 
  	  } else nf_error(_(errmsg[5])); 
  	} 
#else 
      nf_error(_(errmsg[5])); 
#endif 
      
      /* >>>>>>>>>>>> Light Curve <<<<<<<<<<<<<<<<<<<<<<<<<< */
      /* photometric zeropoint                               */
      Calib = FluxOut[0].Mag[Vmag];

      /* get photometric data and scale                      */
      js = 0;
      MinMag  = 10.;  
      MaxMag  = -10.; 
      FluxPtr = FluxOut; 

      /* 2002-05-03 rwichmann: the problem is that 
	 lightcurve normalization has been done already, resulting
	 in MinMag = nan  MaxMag = nan.
      */
      for (i = 0; i <= phaseind; ++i) { 
	if (i == 0 || FluxPtr->Mag[Vmag] != 0)
	  {
	    if (fabs(Calib) < DBL_EPSILON) {
	      /* already normalized                              */
	      Yplot[js] = - FluxPtr->Mag[Vmag];
	    }
	    else { 
	      /* normalize and transform flux -> magnitude       */
	      Yplot[js] = 2.5 * log10(FluxPtr->Mag[Vmag]/Calib);
	    }
	    MinMag  = MIN(MinMag,Yplot[js]); MaxMag  = MAX(MaxMag,Yplot[js]); 
	    Xplot[js] = (FluxPtr->Phase/(PI+PI)) - 0.5;
	    ++js;
	  }
  	++FluxPtr;  
      } 

      /* shift phase if necessary                            */
      test = ON;
      do { 
  	if (Xplot[0] > 0.0) { 
  	  for (i = 0; i <= js; ++i) { 
  	    Xplot[i] = Xplot[i] - 1.0; 
 	  } 
	  test = ON;  /* there was something to do           */
  	} else { 
  	  if (Xplot[0] < (-1.0)) { 
  	    for (i = 0; i <= js; ++i) { 
  	      Xplot[i] = Xplot[i] + 1.0; 
  	    } 
	    test = ON;  /* there was something to do         */ 
  	  } else { test = OFF; }
  	} 
      } while (test == ON); 
      
      if (fabs(MinMag-MaxMag) < 0.1) MinMag = -0.1; 

      /* plot box                                            */
      Xtick = (int)(100.*(MaxMag-MinMag+0.1)/3.)/100.; 

      CoordSys[LIGHTCURVE] = 
	SetupCoords(MinMag,MaxMag,"Phase","M","Light Curve");
      
      /* plot coordinate system                              */
      GLMake2DAxes(CoordSys[LIGHTCURVE], glArea);

      glPointSize(2);
      glDisable(GL_LIGHTING);
      
      glColor3f(1.0, 1.0, 0.0);
      glBegin(GL_POINTS);
      for (i = 0; i < js; ++i) { 
	glVertex2f(Xplot[i], Yplot[i]);
      }
      glEnd();

      glEnable(GL_LIGHTING);
      glPointSize(1);
     
      free(Xplot);
      free(Yplot);
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   1.0
 @short     The radial velocity drawing code 
 @param     (void)
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLMakeRVPlot ( void )
{
  double    Calib;                 /* normalization for flux         */
  int       i,test;
  float     *Xplot,*Yplot,*Zplot;  /* x, y, z position                  */
  float     MinVel, MaxVel;        /* plot scaling           */
  PhotoOut  *FluxPtr = FluxOut;    /* pointer to flux                */
  int    js;                       /* j minus invalid                */

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      /* Initialize memory for plot                               */
      /* Initialize memory for plot                               */
      Xplot = malloc(3 * MAXELEMENTS * sizeof(float)); 
      Yplot = malloc(3 * MAXELEMENTS * sizeof(float)); 
      Zplot = malloc(3 * MAXELEMENTS * sizeof(float)); 

      if (Xplot == NULL || Yplot == NULL) 
#ifdef _WITH_GTK 
  	{  
	  if (Flags.interactive == ON) { 
  	    make_dialog (_(errmsg[0])); 
  	    if (Xplot != NULL) free(Xplot); 
  	    if (Yplot != NULL) free(Yplot); 
  	    return; 
  	  } else nf_error(_(errmsg[5])); 
  	} 
  #else 
        nf_error(_(errmsg[5])); 
#endif 
      /* >>>>>>>>>>>> Light Curve <<<<<<<<<<<<<<<<<<<<<<<<<< */
      /* photometric zeropoint                               */
      Calib = FluxOut[0].Mag[Vmag];
      
      /* get photometric data and scale                      */
      js = 0;
      MinVel  = (FluxPtr->RV[Primary])  /1000.;
      MaxVel  = (FluxPtr->RV[Secondary])/1000.; 

      if (Flags.elliptic == ON) {
	for (i = 0; i <= phaseind; ++i) {
	  if (i == 0 || FluxPtr->Mag[Vmag] != 0)
	    {
	      Xplot[js] = (FluxPtr->Phase/(PI+PI)) - 0.5;  
	      Yplot[js] =   (FluxPtr->RV[Primary])  /1000.;
	      Zplot[js] =   (FluxPtr->RV[Secondary])/1000.;
	      MinVel  = MIN(MinVel,Yplot[js]); MaxVel = MAX(MaxVel,Yplot[js]);
	      MinVel  = MIN(MinVel,Zplot[js]); MaxVel = MAX(MaxVel,Zplot[js]);
	      ++js;
	    }
	  ++FluxPtr;
	}
      } else {
	for (i = 0; i <= phaseind; ++i) {
	  if (i == 0 || FluxPtr->Mag[Vmag] != 0)
	    {
	      Xplot[js] = (FluxPtr->Phase/(PI+PI)) - 0.5;  
	      Yplot[js] = - (FluxPtr->RV[Primary])  /1000.;
	      Zplot[js] = - (FluxPtr->RV[Secondary])/1000.;
	      MinVel  = MIN(MinVel,Yplot[js]); MaxVel  = MAX(MaxVel,Yplot[js]);
	      MinVel  = MIN(MinVel,Zplot[js]); MaxVel  = MAX(MaxVel,Zplot[js]);
	      ++js;
	    }
	  ++FluxPtr;
	}
      }

      /* shift phase if necessary                            */
      test = ON;
      do { 
  	if (Xplot[0] > 0.0) { 
  	  for (i = 0; i <= js; ++i) { 
  	    Xplot[i] = Xplot[i] - 1.0; 
 	  } 
	  test = ON;  /* there was something to do           */
  	} else { 
  	  if (Xplot[0] < (-1.0)) { 
  	    for (i = 0; i <= js; ++i) { 
  	      Xplot[i] = Xplot[i] + 1.0; 
  	    } 
	    test = ON;  /* there was something to do         */ 
  	  } else { test = OFF; }
  	} 
      } while (test == ON); 
     
      if (fabs(MinVel-MaxVel) < 5.) { 
	MinVel = -5.01;
	MaxVel = 5.01; 
      }

      /* plot box                                            */
      CoordSys[RADVELOCITY] = 
	SetupCoords(MinVel, MaxVel,"Phase","v","Radial Velocity");

      /* plot coordinate system                         */
      GLMake2DAxes(CoordSys[RADVELOCITY], glArea);

      glPointSize(2);
      glDisable(GL_LIGHTING);
      
      glBegin(GL_POINTS);
      for (i = 0; i < js; ++i) { 
	/* Primary data (red)               */
	glColor3f(1.0, 0.37, 0.0);
	glVertex2f(Xplot[i], Yplot[i]);
	/* Secondary data (blue)            */
	glColor3f(0.6, 0.86, 1.0);
	glVertex2f(Xplot[i], Zplot[i]);
      }
      glEnd();

      glEnable(GL_LIGHTING);
      glPointSize(1);
     
      free(Xplot);
      free(Yplot);
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   1.0
 @short     Draw x-, y- and z-axes of the binary systems reference 
            coordinate system according to Djurasevic, 1991
	    Note: this is not the OpenGL Viewing coordinate 
	          system !!
 @param     (GLfloat) length  length of the axes
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLDrawAxes(GLfloat length, GtkWidget *widget)
{
  float com;

  /* the x coordinate of the center of mass                      */
  com = (((float)(Binary[Primary].Mq))/( 1.0 + (float)(Binary[Primary].Mq)));

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      /* draw axes with thick lines                    */
      glLineWidth(2);
      
      /* disable lighting, we don't want ligthing with */
      /* the axes                                      */
      glDisable(GL_LIGHTING);
      
      /* draw axes as lines                            */
      glBegin(GL_LINES);
      /* blue x-axis                                   */
      glColor3f(0.0, 0.0, 1.0);
      glVertex3f(com, 0.0, 0.0);
      glVertex3f(com+length, 0.0, 0.0);

      /* green y-axis                                  */
      glColor3f(0.0, 1.0, 0.0);
      glVertex3f(com, 0.0, 0.0);
      glVertex3f(com, -length, 0.0);
      
      /* red z-axis                                    */
      glColor3f(1.0, 0.0, 0.0);
      glVertex3f(com, 0.0, 0.0);
      glVertex3f(com, 0.0, length);
      glEnd();
      
      /* switch on lighing                             */
      glEnable(GL_LIGHTING);
      
      /* set line width to 1                           */
      glLineWidth(1);
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   1.1
 @short     Build a display list for x- and y-axes of the 
            coordinate system
 @param     (GLfloat) length  length of the axes
 @return    (void)   
 @heading   Open GL Animation
*******************************************************************/
void GLMake2DAxes(CoordType coord, GtkWidget *widget)
{
  float length_x, length_y, eye_x;
  float top_xtick, bot_xtick;
  float xmin_border,xmax_border,ymin_border,ymax_border;

  AxisType xaxis;
  AxisType yaxis;
  
  xaxis = coord.xaxis;
  yaxis = coord.yaxis;

  /* length of x- and y-axes                           */
  length_x = xaxis.length;
  length_y = yaxis.length;

  if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
    {
      ymin_border = yaxis.min_value-coord.yborder_size;
      ymax_border = yaxis.max_value+coord.yborder_size;

      xmin_border = xaxis.min_value-coord.xborder_size;
      xmax_border = xaxis.max_value+coord.xborder_size;

      /* viewers position                              */
      eye_x     = xaxis.min_value + 0.5*length_x;
      /* tickmarks on x-axis                           */
      top_xtick = ymin_border     + 0.02*length_y;
      bot_xtick = ymin_border     - 0.02*length_y;

      /* draw axes with thick lines                    */
      glLineWidth(2);
      
      /* disable lighting, we don't want ligthing with */
      /* the axes                                      */
      glDisable(GL_LIGHTING);

      glColor3f(1.0, 1.0, 1.0); 
      /* draw border for plot                                              */
      glBegin(GL_LINES); 
      glVertex2f(xmin_border, ymin_border);
      glVertex2f(xmin_border, ymax_border);      

      glVertex2f(xmin_border, ymax_border);
      glVertex2f(xmax_border, ymax_border);

      glVertex2f(xmax_border, ymax_border);
      glVertex2f(xmax_border, ymin_border);

      glVertex2f(xmax_border, ymin_border);
      glVertex2f(xmin_border, ymin_border);
      glEnd(); 

      /* draw  tickmarks                                                   */
      glBegin(GL_LINES); 
      glVertex2f(-0.5, bot_xtick);       
      glVertex2f(-0.5, top_xtick);       
      glVertex2f( 0.0, bot_xtick);       
      glVertex2f( 0.0, top_xtick);       
      glVertex2f( 0.5, bot_xtick);       
      glVertex2f( 0.5, top_xtick);
      glVertex2f( 1.0, bot_xtick);
      glVertex2f( 1.0, top_xtick);
      glEnd();

      /* select font                                   */
      GLSetFont(HELVETICA, 12);

      glDisable(GL_LIGHTING);
      
      glPushMatrix();

      /* print labels for axes                         */
      glColor3f(1.0, 1.0, 1.0);
      GLDrawStr(eye_x-0.1,yaxis.min_value-0.25*length_y,0.0,xaxis.label);
      GLDrawStr(-0.6,yaxis.min_value+0.5*length_y,0.0,yaxis.label);

      /* print tick marks                              */
      GLDrawStr(-0.545,bot_xtick-0.1*length_y,0.0,"0.5");
      GLDrawStr(-0.05,bot_xtick-0.1*length_y,0.0,"0.0");
      GLDrawStr( 0.455,bot_xtick-0.1*length_y,0.0,"0.5");
      GLDrawStr( 0.96,bot_xtick-0.1*length_y,0.0,"1.0");

      /* print title string                            */
      glColor3f(1.0, 1.0, 1.0);
      GLDrawStr(coord.titlepos,yaxis.max_value+0.15*length_y,0.0,coord.title);

      glPopMatrix();

      /* switch on lighing                             */
      glEnable(GL_LIGHTING);
      
      /* set line width to 1                           */
      glLineWidth(1);
    }
}

/******************************************************************
 @package   nightfall
 @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
 @version   0.9
 @short     Set default parameters for coordinate system
 @param     (float)  ymin    minimum y value
 @param     (float)  ymax    maximum y value
 @param     (char *) xlabel  label of the x-axis
 @param     (char *) ylabel  label of the y-axis
 @param     (char *) title   title of the plot
 @return    (CoordType) structure containing information of the 
                        coordinate system 
 @heading   Open GL Animation
*******************************************************************/
CoordType SetupCoords(float ymin, float ymax, 
		      char *xlabel, char *ylabel, char *title) 
{
  AxisType x,y;
  CoordType coord;
  size_t str_length;

  x = coord.xaxis;
  y = coord.yaxis;
  
  strncpy(coord.title, title , MAX_STR_LEN-1);
  str_length = strlen(title);
  if (str_length <= 12) {
    coord.titlepos = 0.08;
  } else {
    coord.titlepos = 0.02;
  }    

  strncpy(x.label, xlabel, MAX_STR_LEN-1);
  strncpy(y.label, ylabel, MAX_STR_LEN-1);
  
  /* min/max values for x/y axis                                           */
  x.max_value = 1.0;
  x.min_value = -0.5;
  y.max_value = ymax;
  y.min_value = ymin;

  /* set size of border between plot and window  */
  /* to 0.1 axes length                          */
  x.length           = x.max_value - x.min_value;
  coord.xborder_size = 0.0166 * x.length;

  y.length           = y.max_value - y.min_value;
  coord.yborder_size = 0.03 * y.length;

  /* number of tickmarks                        */
  x.numticks = 4;
  y.numticks = 4;

  coord.xaxis = x; 
  coord.yaxis = y;
  return(coord);
}

#endif /* OpenGL end */







syntax highlighted by Code2HTML, v. 0.9.1