/*

gdpc - a program for visualising molecular dynamic simulations
Copyright (C) 2000 Jonas Frantz

    This file is part of gdpc.

    gdpc 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.

    gdpc 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Authors email : jonas.frantz@helsinki.fi

*/

#include <stdlib.h>
#include <math.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <math.h>
#include "parameters.h"


/* These definitions control the change in color over
   one ball in drawingmode 2.                         */
#define comp1 56152-(sin(PI/2)*84304)
#define comp2 56152-(sin(0.875*PI/2)*84304)
#define comp3 56152-(sin(0.750*PI/2)*84304)
#define comp4 56152-(sin(0.625*PI/2)*84304)
#define comp5 56152-(sin(0.500*PI/2)*84304)
#define comp6 56152-(sin(0.375*PI/2)*84304)
#define comp7 58152-(sin(0.250*PI/2)*84304)
#define comp8 60152-(sin(0.125*PI/2)*84304)


/* xcolor contains the default colors for gdpc. */
   gushort xcolor[19][3] = {
               {00000,00000,00000},
               {65535,65535,65535},
               {40000,00000,00000},
               {53000,00000,00000},
               {65535,00000,00000},
               {65535,22000,00000},
               {65535,33000,00000},
               {65535,40000,00000},
               {65535,50000,00000},
               {65000,65000,20000},
               {50000,65000,20000},
               {30000,65000,30000},
               {10000,65535,10000},
               {10000,60000,50000},
               {10000,50000,65535},
               {13000,38000,65535},
               {13000,13000,65535},
               {42000,13000,65535},
               {42000,13000,65535} };


/* xcolorinv contains the inverted colors. */
   gushort xcolorinv[19][3] = {
               {00000,00000,00000},
               {65535,65535,65535},
               {26000,26000,65535},
               {13000,26000,65535},
               {13000,38000,65535},
               {10000,50000,65535},
               {10000,60000,50000},
               {10000,65535,10000},
               {30000,65000,30000},
               {50000,65000,20000},
               {65000,65000,20000},
               {65535,50000,00000},
               {65535,40000,00000},
               {65535,33000,00000},
               {65535,22000,00000},
               {65535,00000,00000},
               {56000,00000,00000},
	       {40000,00000,00000},
	       {40000,00000,00000}};


/* xcoldcolor contains the coldcolor colorset. */
   gushort xcoldcolor[19][3] = {
               {00000,00000,00000},
               {65535,65535,65535},
               {255*256,224*256,255*256},
               {224*256,192*256,255*256},
               {192*256,160*256,255*256},
               {160*256,128*256,255*256},
               {128*256, 64*256,255*256},
               { 64*256,  0*256,255*256},
               {  0*256,  0*256,255*256},
               { 64*256,  0*256,224*256},
               {128*256,  0*256,192*256},
               {160*256,  0*256,160*256},
               {192*256,  0*256,128*256},
               {224*256,  0*256, 96*256},
               {255*256,  0*256,  0*256},
               {224*256,  0*256,  0*256},
               {192*256,  0*256,  0*256},
               {160*256,  0*256,  0*256},
               {157*256,  0*256,  0*256} };


/* xcoldcolor2 contains the coldcolor2 colorset. */
   gushort xcoldcolor2[19][3] = {
               {00000,00000,00000},
               {65535,65535,65535},
               { 64*256,  0*256,255*256},
               {  0*256,  0*256,255*256},
               { 60*256, 20*256,255*256},
               { 90*256, 40*256,240*256},
               {120*256, 80*256,220*256},
               {140*256, 90*256,200*256},
               {160*256,100*256,180*256},
               {180*256, 90*256,160*256},
               {200*256, 80*256,128*256},
               {220*256, 40*256, 96*256},
               {236*256, 20*256, 64*256},
               {255*256,  0*256,  0*256},
               {224*256,  0*256,  0*256},
               {192*256,  0*256,  0*256},
               {160*256,  0*256,  0*256},
               {157*256,  0*256, 80*256},
               {157*256,  0*256,120*256} };


/****************************************************************/
/* This function allocates the colors for gdpc according to the */
/* colorset variable or the drawingmode if it is 2.             */
/****************************************************************/
gint allocatecolors (GdkColor **colors,gint colorset,gint mode)
{
gboolean *success;
gint i, ncolors=19;
gint colcomp;
double rcomp, gcomp, bcomp;

    if (mode!=2){
	*colors = (GdkColor *) calloc (ncolors, sizeof(GdkColor));
	success = (gboolean *) calloc (ncolors, sizeof(gboolean));
    }
    else {
	ncolors = 8*17+2;
	*colors = (GdkColor *) calloc (ncolors, sizeof(GdkColor));
	success = (gboolean *) calloc (ncolors, sizeof(gboolean));
    }

    if (colorset==1) {
	for(i=0;i<ncolors;i++) {
	    (*colors)[i].red = xcolorinv[i][0];
	    (*colors)[i].green = xcolorinv[i][1];
	    (*colors)[i].blue = xcolorinv[i][2];
	}
    }
    else if (colorset==2) {
	for(i=0;i<ncolors;i++) {
	    (*colors)[i].red = xcoldcolor[i][0];
	    (*colors)[i].green = xcoldcolor[i][1];
	    (*colors)[i].blue = xcoldcolor[i][2];
	}
    }
    else if (colorset==3) {
	for(i=0;i<ncolors;i++) {
	    (*colors)[i].red = xcoldcolor2[i][0];
	    (*colors)[i].green = xcoldcolor2[i][1];
	    (*colors)[i].blue = xcoldcolor2[i][2];
	}
    }

/* Set the greyscale colors. */
    else if (colorset==4) {
	    i = 0;
	    (*colors)[i].red = 0;
	    (*colors)[i].green = 0;
	    (*colors)[i].blue = 0;
	    i = 1;
	    (*colors)[i].red = 65535;
	    (*colors)[i].green = 65535;
	    (*colors)[i].blue = 65535;
	for(i=2;i<ncolors;i++) {
	    (*colors)[i].red = 65535 - (i-2)*14*256 -2300;
	    (*colors)[i].green = (*colors)[i].red;
	    (*colors)[i].blue = (*colors)[i].red;
	}
    }
    else {
	for(i=0;i<ncolors;i++) {
	    (*colors)[i].red = xcolor[i][0];
	    (*colors)[i].green = xcolor[i][1];
	    (*colors)[i].blue = xcolor[i][2];
	}
    }
/* If drawingmode is 2 than we will create a special set of colors. */
    if (mode==2) {
/* White */
	    (*colors)[0].red = 0;
	    (*colors)[0].green = 0;
	    (*colors)[0].blue = 0;
/* Black */
	    (*colors)[1].red = 65535;
	    (*colors)[1].green = 65535;
	    (*colors)[1].blue = 65535;
	
/* Then we start calculating the actual components of the colors. */
	for(i=0;i<17;i++) {
	    rcomp = cos(i*PI/17);
	    gcomp = sin(i*PI/17);
	    bcomp = -cos(i*PI/17);
	    if(rcomp<0) rcomp = 0;
	    if(gcomp<0) gcomp = 0;
	    if(bcomp<0) bcomp = 0;

	    rcomp = rcomp/sqrt(1.3*rcomp*rcomp+1.2*gcomp*gcomp+0.7*bcomp*bcomp);
	    gcomp = gcomp/sqrt(1.3*rcomp*rcomp+1.2*gcomp*gcomp+0.7*bcomp*bcomp);
	    bcomp = bcomp/sqrt(1.3*rcomp*rcomp+1.2*gcomp*gcomp+0.7*bcomp*bcomp);

	    colcomp = rcomp*65535+comp1;
	    if (colcomp<0) (*colors)[i*8+2].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+2].red = 65535;
	    else (*colors)[i*8+2].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp1;
            if (colcomp<0) (*colors)[i*8+2].green = 0;
            else if (colcomp>65535) (*colors)[i*8+2].green = 65535;
            else (*colors)[i*8+2].green = (gushort) colcomp;         

	    colcomp = bcomp*65535+comp1;
            if (colcomp<0) (*colors)[i*8+2].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+2].blue = 65535;
            else (*colors)[i*8+2].blue = (gushort) colcomp;
         
	    colcomp = rcomp*65535+comp2;
	    if (colcomp<0) (*colors)[i*8+3].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+3].red = 65535;
	    else (*colors)[i*8+3].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp2;
            if (colcomp<0) (*colors)[i*8+3].green = 0;
            else if (colcomp>65535) (*colors)[i*8+3].green = 65535;
            else (*colors)[i*8+3].green = (gushort) colcomp;         

	    colcomp = bcomp*65535+comp2;
            if (colcomp<0) (*colors)[i*8+3].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+3].blue = 65535;
            else (*colors)[i*8+3].blue = (gushort) colcomp;
         
	    colcomp = rcomp*65535+comp3;
	    if (colcomp<0) (*colors)[i*8+4].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+4].red = 65535;
	    else (*colors)[i*8+4].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp3;
            if (colcomp<0) (*colors)[i*8+4].green = 0;
            else if (colcomp>65535) (*colors)[i*8+4].green = 65535;
            else (*colors)[i*8+4].green = (gushort) colcomp;

	    colcomp = bcomp*65535+comp3;
            if (colcomp<0) (*colors)[i*8+4].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+4].blue = 65535;
            else (*colors)[i*8+4].blue = (gushort) colcomp;
         
	    colcomp = rcomp*65535+comp4;
	    if (colcomp<0) (*colors)[i*8+5].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+5].red = 65535;
	    else (*colors)[i*8+5].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp4;
            if (colcomp<0) (*colors)[i*8+5].green = 0;
            else if (colcomp>65535) (*colors)[i*8+5].green = 65535;
            else (*colors)[i*8+5].green = (gushort) colcomp;

	    colcomp = bcomp*65535+comp4;
            if (colcomp<0) (*colors)[i*8+5].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+5].blue = 65535;
            else (*colors)[i*8+5].blue = (gushort) colcomp;
         
	    colcomp = rcomp*65535+comp5;
	    if (colcomp<0) (*colors)[i*8+6].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+6].red = 65535;
	    else (*colors)[i*8+6].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp5;
            if (colcomp<0) (*colors)[i*8+6].green = 0;
            else if (colcomp>65535) (*colors)[i*8+6].green = 65535;
            else (*colors)[i*8+6].green = (gushort) colcomp;

	    colcomp = bcomp*65535+comp5;
            if (colcomp<0) (*colors)[i*8+6].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+6].blue = 65535;
            else (*colors)[i*8+6].blue = (gushort) colcomp;

	    colcomp = rcomp*65535+comp6;
	    if (colcomp<0) (*colors)[i*8+7].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+7].red = 65535;
	    else (*colors)[i*8+7].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp6;
            if (colcomp<0) (*colors)[i*8+7].green = 0;
            else if (colcomp>65535) (*colors)[i*8+7].green = 65535;
            else (*colors)[i*8+7].green = (gushort) colcomp;

	    colcomp = bcomp*65535+comp6;
            if (colcomp<0) (*colors)[i*8+7].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+7].blue = 65535;
            else (*colors)[i*8+7].blue = (gushort) colcomp;

	    colcomp = rcomp*65535+comp7;
	    if (colcomp<0) (*colors)[i*8+8].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+8].red = 65535;
	    else (*colors)[i*8+8].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp7;
            if (colcomp<0) (*colors)[i*8+8].green = 0;
            else if (colcomp>65535) (*colors)[i*8+8].green = 65535;
            else (*colors)[i*8+8].green = (gushort) colcomp;         

	    colcomp = bcomp*65535+comp7;
            if (colcomp<0) (*colors)[i*8+8].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+8].blue = 65535;
            else (*colors)[i*8+8].blue = (gushort) colcomp;

	    colcomp = rcomp*65535+comp8;
	    if (colcomp<0) (*colors)[i*8+9].red = 0;
	    else if (colcomp>65535) (*colors)[i*8+9].red = 65535;
	    else (*colors)[i*8+9].red = (gushort) colcomp;

	    colcomp = gcomp*65535+comp8;
            if (colcomp<0) (*colors)[i*8+9].green = 0;
            else if (colcomp>65535) (*colors)[i*8+9].green = 65535;
            else (*colors)[i*8+9].green = (gushort) colcomp;         

	    colcomp = bcomp*65535+comp8;
            if (colcomp<0) (*colors)[i*8+9].blue = 0;
            else if (colcomp>65535) (*colors)[i*8+9].blue = 65535;
            else (*colors)[i*8+9].blue = (gushort) colcomp;
	}
    }

/* When we're done setting the colors we allocate them. */
    if (gdk_colormap_alloc_colors(gdk_colormap_get_system(),
				  *colors, ncolors, FALSE, 
				  FALSE, success))
        g_error("Can't allocate colors\n");

    return ncolors;
}
