/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Damien
	CALISTE, laboratoire L_Sim, (2001-2009)
        David WAROQUIERS, PCPM UC Louvain la Neuve (2009)
  
	Adresse mèl :
	WAROQUIERS, david P waroquiers AT uclouvain P be
	CALISTE, damien P caliste AT cea P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Damien
	CALISTE, laboratoire L_Sim, (2001-2009)
        David WAROQUIERS, PCPM UC Louvain la Neuve (2009)

	E-mail address:
	CALISTE, damien P caliste AT cea P fr
	WAROQUIERS, david P waroquiers AT uclouvain P be

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at COPYING.
*/
#include "rings.h"

#include <string.h>
#include <math.h>

#include <extraFunctions/plane.h>
#include <coreTools/toolMatrix.h>

#include <openGLFunctions/objectList.h>

/**
 * SECTION: rings
 * @short_description: an extension to highlight closed rings in a structure.
 *
 * <para>TODO</para>
 */

static VisuGlExt* extRings;
static gboolean extRingsIsBuilt;
/* static gulong popInc_signal, popDec_signal, popChg_signal; */

/* Local callbacks. */
/* static void onNodePopulationChanged(VisuData *dataObj, GArray *nodes, gpointer data); */
/* static void onPositionChanged(VisuData *dataObj, gpointer data _U_); */

/* Local routines. */
/* static void rebuildRings(VisuGlExt *ext, VisuData *dataObj, */
/*                          VisuGlView *view, gpointer data); */
void changeCoordfromBoxChange(VisuData *dataObj, float *coord, float boxChange[3], float *newcoord);


#define RADTODEG 57.29577951

/* Some test rings that are relevant */
#define NB_NODES8 8
#define NB_NODES16 16
#define NB_NODES10 10
#define NB_NODES5 5

#define NB_NODES NB_NODES16

int testring_1[NB_NODES8] = {30,69,14,60,2,55,31,71}; /* NB_NODES 8*/
int testring_2[NB_NODES8] = {10,53,15,50,22,71,11,67}; /* NB_NODES 8*/
int testring_3[NB_NODES16] = {2,55,46,64,4,67,11,71,30,69,45,56,6,65,3,60}; /* NB_NODES 16*/
int testring_4[NB_NODES16] = {6,56,45,69,30,71,11,67,10,53,43,63,23,51,35,65}; /* NB_NODES 16*/
int testring[NB_NODES16] = {22,50,9,68,36,63,23,51,35,65,3,60,14,69,30,71}; /* NB_NODES 16*/
int testring_6[NB_NODES10] = {26,54,47,69,30,71,31,55,21,66}; /* NB_NODES 10*/
int testring_7[NB_NODES5] = {60,39,8,61,14}; /* NB_NODES 10*/



typedef struct
{
  int drawSpheres;
  int drawCylinders;
  int drawTrianglePlanars;
  float sphereRadius;
  float sphereColor[4];
  float cylinderRadius;
  float cylinderColor[4];
  float trianglePlanarsColor[4];
} ringVisualisation;

/**
 * initExtRings: (skip)
 *
 * Initialise the ring extension, internal routine, do not use.
 *
 * Since: 3.5
 *
 * Returns: a newly allocated #VisuGlExt.
 */
VisuGlExt* initExtRings()
{
  /* char *name = EXT_RINGS_ID; */
  /* char *description = _("Draw a representation for the rings in an atomic structures."); */

  DBG_fprintf(stderr,"Ext Rings: initialising the rings OpenGL extension...\n");

  /* extRings  = visu_gl_ext_new(name, _(name), description, */
  /*                                1, rebuildRings, (gpointer)0); */
  /* visu_gl_ext_setActive(extRings, FALSE); */
  extRings = (VisuGlExt*)0;

  extRingsIsBuilt = FALSE;

  /* Disable rings extension for now. */
  return extRings;
}
/**
 * extRingsSet_isOn:
 * @value: a boolean.
 *
 * Set if rings are drawn or not.
 *
 * Since: 3.5
 *
 * Returns: TRUE is status is changed.
 */
gboolean extRingsSet_isOn(gboolean value)
{
  if (!visu_gl_ext_setActive(extRings, value))
    return FALSE;

  return (value && !extRingsIsBuilt);
}
/**
 * extRingsGet_isOn:
 *
 * Retrieves if the ring extension is used.
 *
 * Since: 3.5
 *
 * Returns: TRUE if ring extension is used.
 */
gboolean extRingsGet_isOn()
{
  return visu_gl_ext_getActive(extRings);
}

/* static void onDataReadySignal(GObject *obj _U_, VisuData *dataObj, */
/*                               VisuGlView *view, gpointer data _U_) */
/* { */
/*   DBG_fprintf(stderr, "Ext Rings: catch 'dataRendered' signal.\n"); */
/*   if (dataObj && visu_gl_ext_getActive(extRings)) */
/*     { */
/*       if (visu_data_getChangeElementFlag(dataObj)) */
/* 	{ */
/* 	  DBG_fprintf(stderr,"Ext Rings: elements not changed, keep it.\n"); */
/* 	  return; */
/* 	} */
/*       extRingsIsBuilt = FALSE; */
/*       extRingsDraw(dataObj); */
/*     } */
/*   if (dataObj && view) */
/*     { */
/*       popInc_signal = */
/*         g_signal_connect(G_OBJECT(dataObj), "PopulationIncrease", */
/*                          G_CALLBACK(onNodePopulationChanged), (gpointer)0); */
/*       popDec_signal = */
/*         g_signal_connect(G_OBJECT(dataObj), "PopulationDecrease", */
/*                          G_CALLBACK(onNodePopulationChanged), (gpointer)0); */
/*       popChg_signal = */
/*         g_signal_connect(G_OBJECT(dataObj), "PositionChanged", */
/*                          G_CALLBACK(onPositionChanged), (gpointer)0); */
/*     } */
/* } */
/* static void onDataNotReadySignal(GObject *obj _U_, VisuData *dataObj, */
/*                                  VisuGlView *view _U_, gpointer data _U_) */
/* { */
/*   g_signal_handler_disconnect(G_OBJECT(dataObj), popInc_signal); */
/*   g_signal_handler_disconnect(G_OBJECT(dataObj), popDec_signal); */
/*   g_signal_handler_disconnect(G_OBJECT(dataObj), popChg_signal); */
/* } */
/* static void onNodePopulationChanged(VisuData *dataObj, GArray *nodes _U_, */
/* 				    gpointer data _U_) */
/* { */
/*   if (visu_gl_ext_getActive(extRings)) */
/*     { */
/*       extRingsIsBuilt = FALSE; */
/*       extRingsDraw(dataObj); */
/*     } */
/* } */
/* static void onPositionChanged(VisuData *dataObj, gpointer data _U_) */
/* { */
/*   if (visu_gl_ext_getActive(extRings)) */
/*     { */
/*       extRingsIsBuilt = FALSE; */
/*       extRingsDraw(dataObj); */
/*     } */
/* } */

/* static void rebuildRings(VisuGlExt *ext _U_, VisuData *dataObj, */
/*                          VisuGlView *view _U_, gpointer data _U_) */
/* { */
/*   extRingsIsBuilt = FALSE; */
/*   extRingsDraw(dataObj); */
/* } */

void drawCylinder(float x1, float y1, float z1, float x2, float y2, float z2, float cylRad, int nFaces)
{
  double vNorm[3];
  double vDest[3];
  double cosAlpha;
  double alpha;
  double distsq;
  GLUquadricObj *obj;

  DBG_fprintf(stderr, "Drawing Cylinder between points (%.4f,%.4f,%.4f) and (%.4f,%.4f,%.4f)\n",x1 , y1 , z1, x2, y2, z2);

  vDest[0] = x2 - x1;
  vDest[1] = y2 - y1;
  vDest[2] = z2 - z1;
  distsq = (vDest[0]*vDest[0])+(vDest[1]*vDest[1])+(vDest[2]*vDest[2]);
  if (vDest[0] != 0 || vDest[1] != 0)
    {
      vNorm[0] = - vDest[1];
      vNorm[1] = vDest[0];
      vNorm[2] = 0.;
      cosAlpha = sqrt((vDest[2] * vDest[2]) / distsq);
      if (vDest[2] < 0.)
        cosAlpha = - cosAlpha;
      cosAlpha = CLAMP(cosAlpha, -1., 1.);
      alpha = acos(cosAlpha) * RADTODEG;
    }
  else
    {
      vNorm[0] = 1.;
      vNorm[1] = 0.;
      vNorm[2] = 0.;
      if (vDest[2] < 0.)
        alpha = 180.;
      else
        alpha = 0.;
    }
  obj = gluNewQuadric();
  glPushMatrix();
  glTranslated(x1, y1, z1);
  glRotated(alpha, vNorm[0], vNorm[1], vNorm[2]);
  gluCylinder(obj, (GLdouble)cylRad, (GLdouble)cylRad,
	(GLdouble)sqrt(distsq), (GLint)nFaces, (GLint)1);
  glPopMatrix();
  gluDeleteQuadric(obj);
}

void drawSphere(float x1, float y1, float z1, float sphRad, int longit, int latit)
{
  GLUquadricObj *obj;

  DBG_fprintf(stderr, "Drawing Sphere at point (%.4f,%.4f,%.4f)\n",x1 , y1 , z1);
  obj = gluNewQuadric();
  glPushMatrix();
  glTranslated(x1, y1, z1);
  gluSphere(obj, sphRad, longit, latit);
  glPopMatrix();
  gluDeleteQuadric(obj);
}

void drawRingPlanar(int ringSize, float *xyzPts, float *boxRing, float bary[3], float baryBox[3])
{
  int i;
  glBegin(GL_TRIANGLES);
  for (i = 0; i < ringSize-1; i++)
    {
      if (baryBox[0] == *(boxRing + i*3) && baryBox[1] == *(boxRing + i*3 + 1) && baryBox[2] == *(boxRing + i*3 + 2))
        {
          if (baryBox[0] == *(boxRing + i*3 + 3) && baryBox[1] == *(boxRing + i*3 + 4) && baryBox[2] == *(boxRing + i*3 + 5))
            {
              glVertex3fv(bary);
              glVertex3fv(xyzPts + i*3);
              glVertex3fv(xyzPts + i*3 + 3);
            }
        }
    }
  if (baryBox[0] == *(boxRing + (ringSize-1)*3) && baryBox[1] == *(boxRing + (ringSize-1)*3 + 1) && baryBox[2] == *(boxRing + (ringSize-1)*3 + 2))
    {
      if (baryBox[0] == *(boxRing) && baryBox[1] == *(boxRing + 1) && baryBox[2] == *(boxRing + 2))
        {
          glVertex3fv(bary);
          glVertex3fv(xyzPts + (ringSize-1)*3);
          glVertex3fv(xyzPts);
        }
    }
  glEnd();
}

void computeBaryCenter(VisuData *dataObj, int ringSize, float *xyz, float *boxRing, float *baryCoord, float *baryBox)
{
  int i;
  int bBox[3];
  float sum[3] = {0.0,0.0,0.0};
  float tmp[3];
  float tmp2[3];
  DBG_fprintf(stderr, "Computing barycenter of the ring\n");
  for (i = 0; i < ringSize; i++)
    {
      tmp[0] = *(boxRing + 3*i);
      tmp[1] = *(boxRing + 3*i + 1);
      tmp[2] = *(boxRing + 3*i + 2);
      tmp2[0] = *(xyz + 3*i);
      tmp2[1] = *(xyz + 3*i + 1);
      tmp2[2] = *(xyz + 3*i + 2);
      changeCoordfromBoxChange(dataObj, tmp2, tmp, baryCoord);
      sum[0] = sum[0] + *(baryCoord);
      sum[1] = sum[1] + *(baryCoord + 1);
      sum[2] = sum[2] + *(baryCoord + 2);
    }
  *(baryCoord) = sum[0]/ringSize;
  *(baryCoord + 1) = sum[1]/ringSize;
  *(baryCoord + 2) = sum[2]/ringSize;
  visu_data_getNodeBoxFromCoord(dataObj, baryCoord, bBox);
  *(baryBox) = (float)bBox[0];
  *(baryBox + 1) = (float)bBox[1];
  *(baryBox + 2) = (float)bBox[2];
  tmp[0] = -*(baryBox);
  tmp[1] = -*(baryBox + 1);
  tmp[2] = -*(baryBox + 2);
  tmp2[0] = *(baryCoord);
  tmp2[1] = *(baryCoord + 1);
  tmp2[2] = *(baryCoord + 2);
  changeCoordfromBoxChange(dataObj, tmp2, tmp, baryCoord);
  DBG_fprintf(stderr, "Barycenter of the ring :\n   - coordinates (in center box) : %f %f %f \n   - box associated : %f %f %f \n", *(baryCoord), *(baryCoord + 1), *(baryCoord + 2), *(baryBox), *(baryBox + 1), *(baryBox + 2));
}

void drawRingCylinder(int nbOfPairs, float *xyzPts)
{
  float radius = 0.3;
  int nFaces = 10;
  int i;
  for (i = 0; i < nbOfPairs; i++)
    {
      drawCylinder((xyzPts + i*6)[0], (xyzPts + i*6)[1], (xyzPts + i*6)[2],
	(xyzPts + i*6 + 3)[0],(xyzPts + i*6 + 3)[1], (xyzPts + i*6 + 3)[2], radius, nFaces);
    }
}

void drawRingSpheres(int nbOfPairs, float *xyzPts, int *atomInd)
{
  int i;
  for (i = 0; i < 2*nbOfPairs; i++)
    {
      if (*(atomInd + i))
        drawSphere(*(xyzPts + 3*i), *(xyzPts + 3*i + 1), *(xyzPts + 3*i + 2), 0.4, 10, 10);
    }
}

void drawRingLine(int nbOfPairs, float *xyzPts)
{
  int i;
  glBegin(GL_LINES);
  for (i = 0; i < nbOfPairs; i++)
    {
      glVertex3fv(xyzPts + i * 6);
      glVertex3fv(xyzPts + i * 6 + 3);
    }
  glEnd();
}

void initTranslationForBoxAndCoord(VisuData *dataObj, int ringSize, float *xyz, float *boxRing)
{
  float xyzTrans[3];
  float boxTrans[3];
  int i, j, nodeBox[3];

  visu_pointset_getTranslation(VISU_POINTSET(dataObj), boxTrans);
  DBG_fprintf(stderr, "Initializing translation for the box indices and coordinates of the ring : \n");
  DBG_fprintf(stderr, "  with a box translation of %f %f %f\n", boxTrans[0], boxTrans[1], boxTrans[2]);
  DBG_fprintf(stderr, "Initializing translation for the box indices and coordinates of the ring : \n");
  for (i = 0; i < ringSize; i++) /* Get the coordinates of the nodes */
    {
      for (j = 0; j < 3; j++)
        {
          xyzTrans[j] = *(xyz + 3*i + j) + boxTrans[j];
   /*       *(boxRing + 3*i + j) = *(boxRing + 3*i + j);*/
        }
      visu_data_getNodeBoxFromCoord(dataObj, xyzTrans, nodeBox);
      for (j = 0; j < 3; j++)
        {
          DBG_fprintf(stderr, " %d", nodeBox[j]);
          *(boxRing + 3*i + j) = *(boxRing + 3*i + j) + nodeBox[j];
        }
      DBG_fprintf(stderr, "\n");
    }
  g_free(boxTrans);
}

void initRing(VisuData *dataObj _U_, int ringSize, float *xyz _U_, float *boxRing, float *boxChange, int *totNbPts)
{
  int i, j;
/*   float initBoxChange[ringSize][3]; */

  *totNbPts = ringSize;
  DBG_fprintf(stderr, "Initializing boxChange of a ring : \n");

  for (i = 0; i < ringSize-1; i++)
    {
      for (j = 0; j < 3; j++)
        {
          *(boxChange + 3*i + j) = *(boxRing + 3*(i+1) + j) - *(boxRing + 3*i + j);
          DBG_fprintf(stderr, " %.1f", *(boxChange + 3*i + j));
        }
      DBG_fprintf(stderr, "\n");
    }
  for (j = 0; j < 3; j++)
    {
      *(boxChange + 3*(ringSize-1) + j) = *(boxRing  + j) - *(boxRing + 3*(ringSize-1) + j);
      DBG_fprintf(stderr, " %.1f", *(boxChange + 3*(ringSize-1) + j));
    }
  DBG_fprintf(stderr, "\n");
  for (i = 0; i < ringSize; i++) /* Calculate the total number of points needed to draw the rings */
    {
      for (j = 0; j < 3; j++)
        {
          *totNbPts = *totNbPts + ABS(*(boxChange + 3*i + j));
        }
    }
    *totNbPts = *totNbPts * 2;
    DBG_fprintf(stderr, "Total number of points for this ring (including intersections with the box) : %d \n",*totNbPts);
}

void changeCoordfromBoxChange(VisuData *dataObj, float *coord, float boxChange[3], float *newcoord)
{
  float xyz[3], bxyz[3];
  int i;
  xyz[0] = *(coord);
  xyz[1] = *(coord + 1);
  xyz[2] = *(coord + 2);
  visu_box_convertXYZtoBoxCoordinates(visu_boxed_getBox(VISU_BOXED(dataObj)), bxyz, xyz);
  for (i = 0; i < 3; i++)
    {
      bxyz[i] = bxyz[i] + boxChange[i];
    }
  visu_box_convertBoxCoordinatestoXYZ(visu_boxed_getBox(VISU_BOXED(dataObj)), (float*)newcoord, bxyz);
  DBG_fprintf(stderr, "Changing coordinate (%f %f %f) from box change (%.1f %.1f %.1f) to (%f %f %f)\n",
		xyz[0],xyz[1],xyz[2],boxChange[0],boxChange[1],boxChange[2],*(newcoord),*(newcoord + 1),*(newcoord + 2));
}

void setVisuPlaneFromBoxChange(VisuData *dataObj, float boxChange[3], VisuPlane *plane)
{
  float tmpCoord[3], norm, distToOrigin = 0;
  float boxMatrix[3][3];
  float boxToOrtho[3][3];
  float normal[3];
  float bC[3];
  float point[3];
/*  float xyz[3];*/
  int i, j;
  /* Change the transformation matrix. */

  DBG_fprintf(stderr, "Setting a new plane from boxchange %.1f %.1f %.1f :\n", boxChange[0], boxChange[1], boxChange[2]);
  for (j = 0; j < 3; j++)
    {
      if (boxChange[j] < 0.)
        bC[j] = boxChange[j] + 1.;
      else
        bC[j] = boxChange[j];
      tmpCoord[0] = (j == 0)?1.:0.;
      tmpCoord[1] = (j == 1)?1.:0.;
      tmpCoord[2] = (j == 2)?1.:0.;
      visu_box_convertBoxCoordinatestoXYZ(visu_boxed_getBox(VISU_BOXED(dataObj)),
                                          boxMatrix[j], tmpCoord);
    }
  /* We create a matrix to transform the box coordinates to
     cartesian values keeping the orthogonality. */
  for (i = 0; i < 3; i++)
    {
      norm = 0.;
      for (j = 0; j < 3; j++)
	{
	  boxToOrtho[j][i] =
	    boxMatrix[(i + 1)%3][(j + 1)%3] *
	    boxMatrix[(i + 2)%3][(j + 2)%3] -
	    boxMatrix[(i + 1)%3][(j + 2)%3] *
	    boxMatrix[(i + 2)%3][(j + 1)%3];
	  norm += boxToOrtho[j][i] * boxToOrtho[j][i];
	}
      /* We normalise the tranformation matrix. */
      norm = sqrt(norm);
      for (j = 0; j < 3; j++)
	boxToOrtho[j][i] /= norm;
    }
  tool_matrix_productVector(normal, boxToOrtho, boxChange);
  DBG_fprintf(stderr, "  - normal vector : %f %f %f\n", normal[0], normal[1], normal[2]);
  visu_plane_setNormalVector(plane,normal);
  visu_plane_getNVect(plane,normal);
  DBG_fprintf(stderr, "  - normal vector (normalized) : %f %f %f\n", normal[0], normal[1], normal[2]);
  visu_box_convertBoxCoordinatestoXYZ(visu_boxed_getBox(VISU_BOXED(dataObj)), point, bC);
  for (i = 0; i < 3; i++)
  {
    distToOrigin += normal[i]*point[i];
  }
  DBG_fprintf(stderr, "  - distance to origin : %f\n", distToOrigin);
  visu_plane_setDistanceFromOrigin(plane, distToOrigin);
}

void initDrawCoord(VisuData *dataObj, int ringSize, int *atomInd, float *xyz,
		   float *boxChange, float *drawCoord, int totalNumberOfPoints _U_)
{/* Initialize the drawCoordinates : for a given ring size RS and a give number of intersected planes NP, 
    the number of coordinates is 2*(RS + NP), ie one pair of coordinates for each element to draw. */
  int i, j, k = 0;
  int np;
  int l, p;
  float A[3], B[3], xrB[3], bC[3], tBC[3] = {0.,0.,0.};

  float *inter;
  float *change;
  int *index;
  VisuPlane **listOfVisuPlanes; /* Number of planes + 1 (in order to get a NULL at the end and stop)*/

  for (j = 0; j < 3; j++)
    {
      *(drawCoord + j) = *(xyz + j);
      *(atomInd) = 1;
    }
  DBG_fprintf(stderr, "Point added (first point) to drawCoord %f %f %f from box (0 0 0)\n",
                        *(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
  k++;
  for (i = 0; i < ringSize-1; i++)
    {
      if ( (*(boxChange + 3*i) == 0.) && (*(boxChange + 3*i + 1) == 0.) && (*(boxChange + 3*i + 2) == 0.) )
        {
          *(drawCoord + 3*k) = *(xyz + 3*(i+1));
          *(drawCoord + 3*k + 1) = *(xyz + 3*(i+1) + 1);
          *(drawCoord + 3*k + 2) = *(xyz + 3*(i+1) + 2);
          DBG_fprintf(stderr, "Point added to drawCoord %f %f %f from box (0 0 0)\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
          *(atomInd + k) = 1;
          k++;
          *(drawCoord + 3*k) = *(xyz + 3*(i+1));
          *(drawCoord + 3*k + 1) = *(xyz + 3*(i+1) + 1);
          *(drawCoord + 3*k + 2) = *(xyz + 3*(i+1) + 2);
          DBG_fprintf(stderr, "Point added to drawCoord %f %f %f from box (0 0 0)\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
          *(atomInd + k) = 1;
          k++;
        }
      else
        {
          np = ABS(*(boxChange + 3*i)) + ABS(*(boxChange + 3*i + 1)) + ABS(*(boxChange + 3*i + 2));
	  inter = g_malloc(sizeof(float) * np * 3);
	  change = g_malloc(sizeof(float) * np * 3);
	  index = g_malloc(sizeof(float) * np);
          for (j = 0; j < 3; j++)
            {
              A[j] = *(xyz + 3*i + j);
              B[j] = *(xyz + 3*(i+1) + j);
            }
          DBG_fprintf(stderr, "Point A : %f %f %f\nPoint B : %f %f %f\n",
		A[0],A[1],A[2],B[0],B[1],B[2]);
          DBG_fprintf(stderr, "BoxChange for B : %.1f %.1f %.1f\n",
		*(boxChange + 3*i),*(boxChange + 3*i + 1),*(boxChange + 3*i + 2));
          visu_box_convertXYZtoBoxCoordinates(visu_boxed_getBox(VISU_BOXED(dataObj)), xrB, B);
          xrB[0] = xrB[0] + *(boxChange + 3*i);
          xrB[1] = xrB[1] + *(boxChange + 3*i + 1);
          xrB[2] = xrB[2] + *(boxChange + 3*i + 2);
          visu_box_convertBoxCoordinatestoXYZ(visu_boxed_getBox(VISU_BOXED(dataObj)), B, xrB);
          DBG_fprintf(stderr, "Point B after BoxChange : %f %f %f\n",B[0],B[1],B[2]);
	  listOfVisuPlanes = g_malloc(sizeof(VisuPlane*) * (np + 1));
          listOfVisuPlanes[np] = (VisuPlane*)0;
          p = 0;
          for (j = 0; j < 3; j++)
            {
              bC[0] = 0.;
              bC[1] = 0.;
              bC[2] = 0.;
              for (l = 0; l < ABS(*(boxChange + 3*i + j)); l++)
                {
                  if (*(boxChange + 3*i + j) > 0.)
                    {
                      bC[j] = (float)(+l+1);
                    }
                  else if (*(boxChange + 3*i + j) < 0.)
                    {
                      bC[j] = (float)(-l-1);
                    }
                  listOfVisuPlanes[p] = visu_plane_newUndefined();
                  setVisuPlaneFromBoxChange(dataObj, bC, listOfVisuPlanes[p]);
                  change[3 * p + 0] = bC[0];
                  change[3 * p + 1] = bC[1];
                  change[3 * p + 2] = bC[2];
                  p++;
                }
            }
          if (visu_plane_class_getOrderedIntersections(np, listOfVisuPlanes, A, B, (float*)inter, (int*)index))
            {
              tBC[0] = 0.;
              tBC[1] = 0.;
              tBC[2] = 0.;
              for (p = 0; p < np; p++)
                {
                  A[0] = inter[3 * p + 0];
                  A[1] = inter[3 * p + 1];
                  A[2] = inter[3 * p + 2];
                  changeCoordfromBoxChange(dataObj, A, tBC, B);
                  *(drawCoord + 3*k) = B[0];
                  *(drawCoord + 3*k + 1) = B[1];
                  *(drawCoord + 3*k + 2) = B[2];
/*                  *(drawCoord + 3*k) = inter[p][0];
                  *(drawCoord + 3*k + 1) = inter[p][1];
                  *(drawCoord + 3*k + 2) = inter[p][2];*/
                  DBG_fprintf(stderr, "Point added to drawCoord %f %f %f for a plane\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
                  *(atomInd + k) = 0;
                  k++;

                  if (change[index[p] * 3 + 0] < 0.)
                    tBC[0] = tBC[0] + 1.;
                  else if (change[index[p] * 3 + 0] > 0.)
                    tBC[0] = tBC[0] - 1.;
                  if (change[index[p] * 3 + 1] < 0.)
                    tBC[1] = tBC[1] + 1.;
                  else if (change[index[p] * 3 + 1] > 0.)
                    tBC[1] = tBC[1] - 1.;
                  if (change[index[p] * 3 + 2] < 0.)
                    tBC[2] = tBC[2] + 1.;
                  else if (change[index[p] * 3 + 2] > 0.)
                    tBC[2] = tBC[2] - 1.;
                  DBG_fprintf(stderr, "Change of box needed for the next point : %f %f %f\n",
			tBC[0],tBC[1],tBC[2]);
                  A[0] = inter[p * 3 + 0];
                  A[1] = inter[p * 3 + 1];
                  A[2] = inter[p * 3 + 2];
                  changeCoordfromBoxChange(dataObj, A, tBC, B);
                  *(drawCoord + 3*k) = B[0];
                  *(drawCoord + 3*k + 1) = B[1];
                  *(drawCoord + 3*k + 2) = B[2];
                  DBG_fprintf(stderr, "Point added to drawCoord %f %f %f for a plane\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
                  *(atomInd + k) = 0;
                  k++;
                }
              *(drawCoord + 3*k) = *(xyz + 3*(i+1));
              *(drawCoord + 3*k + 1) = *(xyz + 3*(i+1) + 1);
              *(drawCoord + 3*k + 2) = *(xyz + 3*(i+1) + 2);
              DBG_fprintf(stderr, "Point added to drawCoord %f %f %f after planes\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
              *(atomInd + k) = 1;
              k++;
              *(drawCoord + 3*k) = *(xyz + 3*(i+1));
              *(drawCoord + 3*k + 1) = *(xyz + 3*(i+1) + 1);
              *(drawCoord + 3*k + 2) = *(xyz + 3*(i+1) + 2);
              DBG_fprintf(stderr, "Point added to drawCoord %f %f %f after planes\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
              *(atomInd + k) = 1;
              k++;
            }
          else
            {
              DBG_fprintf(stderr, "WARNING : visu_plane_class_getOrderedIntersections did not find any plane !!!\n");
            }
	  g_free(listOfVisuPlanes);
	  g_free(inter);
	  g_free(change);
	  g_free(index);
        }
    }

  if ( (*(boxChange + 3*(ringSize-1)) == 0.) && (*(boxChange + 3*(ringSize-1) + 1) == 0.) && (*(boxChange + 3*(ringSize-1) + 2) == 0.) )
    {
      *(drawCoord + 3*k) = *(xyz);
      *(drawCoord + 3*k + 1) = *(xyz + 1);
      *(drawCoord + 3*k + 2) = *(xyz + 2);
      DBG_fprintf(stderr, "Point added to drawCoord %f %f %f from box (0 0 0)\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
      *(atomInd + k) = 1;
      k++;
    }
  else
    {
      np = ABS(*(boxChange + 3*(ringSize-1))) + ABS(*(boxChange + 3*(ringSize-1) + 1)) + ABS(*(boxChange + 3*(ringSize-1) + 2));
      inter = g_malloc(sizeof(float) * np * 3);
      change = g_malloc(sizeof(float) * np * 3);
      index = g_malloc(sizeof(float) * np);
      for (j = 0; j < 3; j++)
        {
          A[j] = *(xyz + 3*(ringSize-1) + j);
          B[j] = *(xyz + j);
        }
      DBG_fprintf(stderr, "Point A : %f %f %f\nPoint B : %f %f %f\n",
		A[0],A[1],A[2],B[0],B[1],B[2]);
      DBG_fprintf(stderr, "BoxChange for B : %.1f %.1f %.1f\n",
		*(boxChange + 3*(ringSize-1)),*(boxChange + 3*(ringSize-1) + 1),
		*(boxChange + 3*(ringSize-1) + 2));
      visu_box_convertXYZtoBoxCoordinates(visu_boxed_getBox(VISU_BOXED(dataObj)), xrB, B);
      xrB[0] = xrB[0] + *(boxChange + 3*(ringSize-1));
      xrB[1] = xrB[1] + *(boxChange + 3*(ringSize-1) + 1);
      xrB[2] = xrB[2] + *(boxChange + 3*(ringSize-1) + 2);
      visu_box_convertBoxCoordinatestoXYZ(visu_boxed_getBox(VISU_BOXED(dataObj)), B, xrB);
      DBG_fprintf(stderr, "Point B after BoxChange : %f %f %f\n",B[0],B[1],B[2]);
      listOfVisuPlanes = g_malloc(sizeof(VisuPlane*) * (np + 1));
      listOfVisuPlanes[np] = (VisuPlane*)0;
      p = 0;
      for (j = 0; j < 3; j++)
        {
          bC[0] = 0.;
          bC[1] = 0.;
          bC[2] = 0.;
          for (l = 0; l < ABS(*(boxChange + 3*(ringSize-1) + j)); l++)
            {
              if (*(boxChange + 3*(ringSize-1) + j) > 0.)
                {
                  bC[j] = (float)(+l+1);
                }
              else if (*(boxChange + 3*(ringSize-1) + j) < 0.)
                {
                  bC[j] = (float)(-l-1);
                }
              listOfVisuPlanes[p] = visu_plane_newUndefined();
              setVisuPlaneFromBoxChange(dataObj, bC, listOfVisuPlanes[p]);
              change[p * 3 + 0] = bC[0];
              change[p * 3 + 1] = bC[1];
              change[p * 3 + 2] = bC[2];
              p++;
            }
        }
      if (visu_plane_class_getOrderedIntersections(np, listOfVisuPlanes, A, B, (float*)inter, (int*)index))
        {
          tBC[0] = 0.;
          tBC[1] = 0.;
          tBC[2] = 0.;
          for (p = 0; p < np; p++)
            {
              A[0] = inter[3 * p + 0];
              A[1] = inter[3 * p + 1];
              A[2] = inter[3 * p + 2];
              changeCoordfromBoxChange(dataObj, A, tBC, B);
              *(drawCoord + 3*k) = B[0];
              *(drawCoord + 3*k + 1) = B[1];
              *(drawCoord + 3*k + 2) = B[2];
/*              *(drawCoord + 3*k) = inter[p][0];
              *(drawCoord + 3*k + 1) = inter[p][1];
              *(drawCoord + 3*k + 2) = inter[p][2];*/
              DBG_fprintf(stderr, "Point added to drawCoord %f %f %f for a plane\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
                  *(atomInd + k) = 0;
              k++;

              if (change[index[p] * 3 + 0] < 0.)
                tBC[0] = tBC[0] + 1.;
              else if (change[index[p] * 3 + 0] > 0.)
                tBC[0] = tBC[0] - 1.;
              if (change[index[p] * 3 + 1] < 0.)
                tBC[1] = tBC[1] + 1.;
              else if (change[index[p] * 3 + 1] > 0.)
                tBC[1] = tBC[1] - 1.;
              if (change[index[p] * 3 + 2] < 0.)
                tBC[2] = tBC[2] + 1.;
              else if (change[index[p] * 3 + 2] > 0.)
                tBC[2] = tBC[2] - 1.;
              DBG_fprintf(stderr, "Change of box needed for the next point : %f %f %f\n",
			tBC[0],tBC[1],tBC[2]);
              A[0] = inter[p * 3 + 0];
              A[1] = inter[p * 3 + 1];
              A[2] = inter[p * 3 + 2];
              changeCoordfromBoxChange(dataObj, A, tBC, B);
              *(drawCoord + 3*k) = B[0];
              *(drawCoord + 3*k + 1) = B[1];
              *(drawCoord + 3*k + 2) = B[2];
              DBG_fprintf(stderr, "Point added to drawCoord %f %f %f for a plane\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
              *(atomInd + k) = 0;
              k++;
            }
          *(drawCoord + 3*k) = *(xyz);
          *(drawCoord + 3*k + 1) = *(xyz + 1);
          *(drawCoord + 3*k + 2) = *(xyz + 2);
          DBG_fprintf(stderr, "Point added to drawCoord %f %f %f after planes\n",
			*(drawCoord + 3*k), *(drawCoord + 3*k + 1), *(drawCoord + 3*k + 2));
          *(atomInd + k) = 1;
          k++;
        }
      else
        {
          DBG_fprintf(stderr, "WARNING : visu_plane_class_getOrderedIntersections did not find any plane !!!\n");
        }
      g_free(listOfVisuPlanes);
      g_free(inter);
      g_free(change);
      g_free(index);
    }
}
/**
 * extRingsDraw:
 * @dataObj: a #VisuData object.
 *
 * Draw the rings (if any).
 *
 * Since: 3.5
 */
void extRingsDraw(VisuData *dataObj)
{

/*   float boxring_1[NB_NODES8][3] = {0.,0.,0.,0.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,0.,0.,0.}; */
/*   float boxring_2[NB_NODES8][3] = {0.,0.,0.}; */
/*   float boxring_3[NB_NODES16][3] = {0.}; */
/*   float boxring_4[NB_NODES16][3] = {0.,0.,0.}; */
/*   float boxring[NB_NODES16][3] = {0.,0.,0.,0.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}; */
/*   float boxring_6[NB_NODES10][3] = {0.,0.,0.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,0.,0.,1.,1.,0.,1.,1.,0.,1.,1.,0.,0.,1.,0.,0.}; */
  float boxring_7[NB_NODES5][3] = {{0.,0.,0.},{0.,0.,0.},{-1.,-1.,-1.},{-1.,-1.,-1.},{0.,0.,0.}};

  /* int bleh; */
  float rgba[4] = {1., 0., 0., 0.5};

  int *my_test = testring;
  int i, j;
  VisuNode *vtmp;
  float sum[3] = {0.0,0.0,0.0};
  float xyz[NB_NODES][3]; /* The initial coordinates */
/*   float XYZ[NB_NODES][3]; */ /* The translated coordinates */
/*   float nodeTrans[NB_NODES][3]; */
  /* float bary[3]; */
  int totalNumberOfPoints;
  float *drawCoord;
  int *atomIndices;
  float boxChange[NB_NODES][3];
/*   float newBoxChange[NB_NODES][3]; */
  float baryCoord[3];
  float baryBox[3];


  if (extRingsIsBuilt || !dataObj)
    return;

  DBG_fprintf(stderr, "Ext Rings: drawing the rings.\n");
  extRingsIsBuilt = TRUE;

  glNewList(visu_gl_ext_getGlList(extRings), GL_COMPILE);

  /* for (i = 0; i < 6; i++) */
  /*   box[i] = visu_data_getBoxGeometry(dataObj, i); */

  /* Put the drawing primitives here. */
  DBG_fprintf(stderr, "Coordinates in initial box :\n");
  for (i = 0; i < NB_NODES; i++) /* Get the coordinates of the nodes */
    {
      vtmp = visu_node_array_getFromId(VISU_NODE_ARRAY(dataObj), my_test[i]);
      xyz[i][0] = vtmp->xyz[0];
      xyz[i][1] = vtmp->xyz[1];
      xyz[i][2] = vtmp->xyz[2];
      for (j = 0; j < 3; j++)
        {
          DBG_fprintf(stderr, "  %f",xyz[i][j]);
          sum[j] = sum[j] + xyz[i][j];
        }
      DBG_fprintf(stderr, "\n");
    }
  /* bary[0] = sum[0]/NB_NODES; /\* Get the barycentre *\/ */
  /* bary[1] = sum[1]/NB_NODES; */
  /* bary[2] = sum[2]/NB_NODES; */


/* INITIALIZING THE BOXRINGS AND COORDINATES */
  initTranslationForBoxAndCoord(dataObj, NB_NODES, (float*)xyz, (float*)boxring_7);
  for (i = 0; i < NB_NODES; i++) /* Get the coordinates of the nodes */
    {
      vtmp = visu_node_array_getFromId(VISU_NODE_ARRAY(dataObj), my_test[i]);
      visu_data_getNodePosition(dataObj, vtmp, xyz[i]);
    }

/* INITIALIZING THE RINGS*/
  initRing(dataObj, NB_NODES, (float*)xyz, (float*)boxring_7, (float*)boxChange, &totalNumberOfPoints);

/*COMPUTE BARYCENTER OF THE RING*/
  computeBaryCenter(dataObj, NB_NODES, (float*)xyz, (float*)boxring_7, (float*)baryCoord, (float*)baryBox);


/*INITIALIZING THE DRAW COORDINATES*/
  atomIndices = g_malloc(sizeof(int) * totalNumberOfPoints);
  drawCoord = g_malloc(sizeof(float) * 3 * totalNumberOfPoints);
  initDrawCoord(dataObj, NB_NODES, (int*)atomIndices, (float*)xyz, (float*)boxChange, (float*)drawCoord, totalNumberOfPoints);

  glDisable(GL_LIGHTING);
  glDisable(GL_CULL_FACE);

  glColor4fv(rgba);

/*   float radius = 0.5; */

  rgba[0] = 0.;
  rgba[1] = 1.;
  rgba[2] = 0.;
  rgba[3] = 0.5;
  glColor4fv(rgba);
  /* bleh = totalNumberOfPoints/2; */
  drawRingPlanar(NB_NODES,(float*)xyz, (float*)boxring_7, baryCoord, baryBox);
  rgba[0] = 0.;
  rgba[1] = 1.;
  rgba[2] = 0.;
  rgba[3] = 1.;
  glColor4fv(rgba);
/*  drawRingCylinder(bleh,(float*)drawCoord);*/
  rgba[0] = 0.;
  rgba[1] = 0.;
  rgba[2] = 1.;
  rgba[3] = 1.;
/*  glColor4fv(rgba);
  drawSphere(baryCoord[0], baryCoord[1], baryCoord[2], 0.5, 10, 10);*/
  rgba[0] = 1.;
  rgba[1] = 0.;
  rgba[2] = 0.;
  rgba[3] = 1.;
  glColor4fv(rgba);
/*  drawRingSpheres(bleh, (float*)drawCoord, (int*)atomIndices);*/
/*  drawRingLine(bleh,(float*)drawCoord);*/

  g_free(atomIndices);
  g_free(drawCoord);

  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEndList();
}
