<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/layoutUI/CQGLNetworkPainter.cpp,v $
//   $Revision: 1.139 $
//   $Name:  $
//   $Author: gauges $
//   $Date: 2008/10/03 19:24:26 $
// End CVS Header

// Copyright (C) 2008 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <qstring.h>
#include <qbitmap.h>
#include <qpainter.h>
#include <qrect.h>
#include <qpoint.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qsize.h>
#include <qcolor.h>
#include <qtimer.h>
#include <qcanvas.h>

#include <qfontinfo.h>
#include <qfontdatabase.h>

#include <iostream>
#include <limits>
#include <math.h>
#include <float.h>
#include <utility>

#include "copasi/utilities/COutputHandler.h"

#include "copasi.h"

#include "FontChooser.h"

#if (defined WIN32 && !defined log2)
C_FLOAT64 log2(const C_FLOAT64 & __x)
{return log(__x) / log(2.0);}
#endif // WIN32

#include "CQGLNetworkPainter.h"
#include "CQLayoutMainWindow.h"

#include "UI/qtUtilities.h"
#include "layout/CLayout.h"
#include "utilities/CCopasiVector.h"
#include "layoutUI/CVisParameters.h"
#include "layoutUI/CDataEntity.h"
#include "layoutUI/BezierCurve.h"

// TODO change the text rendering or the texture creation. Right now it seems
// to work reasonably well under Mac OS X, but under Linux it doesn't.

// TODO Antialias Nodes and arrowheads, right now it looks as if only the edges
// do get antialiasing

// below species and speciesreference
const double CQGLNetworkPainter::COMPARTMENT_DEPTH = 0.001;
const double CQGLNetworkPainter::COMPARTMENT_SHADOW_DEPTH = 0.0009;
const double CQGLNetworkPainter::COMPARTMENT_FRAME_DEPTH = 0.0011;

const double CQGLNetworkPainter::SPECIES_DEPTH = 0.005;
const double CQGLNetworkPainter::SPECIES_SHADOW_DEPTH = 0.0049;
const double CQGLNetworkPainter::SPECIES_FRAME_DEPTH = 0.0051;

//below species
const double CQGLNetworkPainter::SPECIESREFERENCE_DEPTH = 0.003;

const GLfloat CQGLNetworkPainter::MIRROR_X[] =
  {
    1.0f, 0.0f, 0.0f, 0.0f
    , 0.0f, -1.0f, 0.0f, 0.0f
    , 0.0f, 0.0f, 1.0f, 0.0f
    , 0.0f, 0.0f, 0.0f, 1.0f
  };

const GLfloat CQGLNetworkPainter::MIRROR_Y[] =
  {
    -1.0f, 0.0f, 0.0f, 0.0f
    , 0.0f, 1.0f, 0.0f, 0.0f
    , 0.0f, 0.0f, 1.0f, 0.0f
    , 0.0f, 0.0f, 0.0f, 1.0f
  };

CQGLNetworkPainter::CQGLNetworkPainter(const QGLFormat& format, QWidget *parent, const char *name)
    : QGLWidget(format, parent, name)
{
  initializeGraphPainter(parent);
}

CQGLNetworkPainter::~CQGLNetworkPainter()
{
  std::map<std::string, RGTextureSpec*>::iterator it = labelTextureMap.begin(), endit = labelTextureMap.end();
  while (it != endit)
    {
      delete[] it->second->textureData;
      delete it->second;
      ++it;
    }
  // delete the node display list
  glDeleteLists(this->mDisplayLists, 17);
}

void CQGLNetworkPainter::initializeDisplayLists()
{
  glClearColor(mBackgroundColor[0], mBackgroundColor[1], mBackgroundColor[2], mBackgroundColor[3]);
  // convert the node into a display list that is created once and call once
  // for each node.
  // this might safe some cpu cycles, especially when the nodes get more fancy.
  this->mDisplayLists = glGenLists(17);
  // this list is for the rectangular nodes
  GLfloat compartmentColor_080[] = {mCompartmentColor[0] + (1.0f - mCompartmentColor[0]) * 0.8f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1]) * 0.8f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2]) * 0.8f};
  GLfloat speciesColor_080[] = {mSpeciesColor[0] + (1.0f - mSpeciesColor[0]) * 0.8f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1]) * 0.8f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2]) * 0.8f};
  glNewList(mDisplayLists, GL_COMPILE);
  // approximate a quarter circle by a triangle fan with 3 triangles
  glBegin(GL_TRIANGLE_FAN);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.0f, 0.4f, COMPARTMENT_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glColor3f(mCompartmentColor[0] + (1.0f - mCompartmentColor[0])*0.9f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1])*0.9f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2])*0.9f); // 90% value
  glVertex3f(0.05f, 0.4866f, COMPARTMENT_DEPTH);
  glColor3f(mCompartmentColor[0] + (1.0f - mCompartmentColor[0])*0.973f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1])*0.973f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2])*0.973f);  // 97.32% value
  glVertex3f(0.0866f, 0.45f, COMPARTMENT_DEPTH);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.0f, 0.4f, COMPARTMENT_DEPTH);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_DEPTH);
  glColor3fv(mCompartmentColor);
  glVertex3f(0.1f, 0.0f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the line strip a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINE_STRIP);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.05f, 0.4866f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.0866f, 0.45f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.1f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // now copy the first call list and mirror the copy at the x-axis
  glNewList(mDisplayLists + 1, GL_COMPILE);
  glPushMatrix();
  glTranslatef(0.0f, 0.5f, 0.0f);
  glCallList(mDisplayLists);
  // mirror transformation
  glMultMatrixf(MIRROR_X);
  glCallList(mDisplayLists);
  glPopMatrix();
  glEndList();

  // next list is the center piece for the compartment glyph
  glNewList(mDisplayLists + 2, GL_COMPILE);
  glBegin(GL_POLYGON);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 1.0f, COMPARTMENT_DEPTH);
  glVertex3f(1.0f, 1.0f, COMPARTMENT_DEPTH);
  glColor3fv(mCompartmentColor);
  glVertex3f(1.0f, 0.5f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(mCompartmentColor);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glVertex3f(1.0f, 0.5f, COMPARTMENT_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(1.0f, 0.0f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the lines  a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINES);
  glVertex3f(0.0f, 1.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(1.0f, 1.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(1.0f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // call lists for the species nodes
  glNewList(mDisplayLists + 3, GL_COMPILE);
  // approximate a quarter circle by a triangle fan with 3 triangles
  glBegin(GL_TRIANGLE_FAN);
  glColor3fv(speciesColor_080);
  glVertex3f(0.0f, 0.4f, SPECIES_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glColor3f(mSpeciesColor[0] + (1.0f - mSpeciesColor[0])*0.9f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1])*0.9f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2])*0.9f); // 90% value
  glVertex3f(0.05f, 0.4866f, SPECIES_DEPTH);
  glColor3f(mSpeciesColor[0] + (1.0f - mSpeciesColor[0])*0.973f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1])*0.973f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2])*0.973f);  // 97.32% value
  glVertex3f(0.0866f, 0.45f, SPECIES_DEPTH);
  glColor3fv(speciesColor_080);
  glVertex3f(0.1f, 0.4f, SPECIES_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(speciesColor_080);
  glVertex3f(0.0f, 0.4f, SPECIES_DEPTH);
  glVertex3f(0.1f, 0.4f, SPECIES_DEPTH);
  glColor4fv(mSpeciesColor);
  glVertex3f(0.1f, 0.0f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the line strip a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINE_STRIP);
  glVertex3f(0.0f, 0.5f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.05f, 0.4866f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.0866f, 0.45f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.1f, 0.4f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.1f, 0.0f, SPECIES_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // now copy the first call list and mirror the copy at the x-axis
  glNewList(mDisplayLists + 4, GL_COMPILE);
  glPushMatrix();
  glTranslatef(0.0f, 0.5f, 0.0f);
  glCallList(mDisplayLists + 3);
  // mirror transformation
  glMultMatrixf(MIRROR_X);
  glCallList(mDisplayLists + 3);
  glPopMatrix();
  glEndList();

  // next list is the center piece for the species glyph
  glNewList(mDisplayLists + 5, GL_COMPILE);
  glBegin(GL_POLYGON);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 1.0f, SPECIES_DEPTH);
  glVertex3f(1.0f, 1.0f, SPECIES_DEPTH);
  glColor3fv(mSpeciesColor);
  glVertex3f(1.0f, 0.5f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(mSpeciesColor);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glVertex3f(1.0f, 0.5f, SPECIES_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(1.0f, 0.0f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the lines  a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINES);
  glVertex3f(0.0f, 1.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(1.0f, 1.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(1.0f, 0.0f, SPECIES_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // display lists for arrow heads (try to be SBGN like)

  // head for stimulation (unfilled arrow)
  glNewList(mDisplayLists + 6, GL_COMPILE);
  glColor4fv(mBackgroundColor);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glDisable(GL_DEPTH_TEST);
  glLineWidth(2.0f);
  glBegin(GL_LINE_LOOP);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glLineWidth(1.0f);
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // head for transition (filled arrow head)
  glNewList(mDisplayLists + 7, GL_COMPILE);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glEndList();

  // head for inhibition (perpendicular bar)
  glNewList(mDisplayLists + 8, GL_COMPILE);
  glBegin(GL_POLYGON);
  glVertex3f(-3.0f, 0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(3.0f, 0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(3.0f, -0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-3.0f, -0.5f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glEndList();

  // head for modulation (unfilled diamond)
  glNewList(mDisplayLists + 9, GL_COMPILE);
  glColor4fv(mBackgroundColor);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -6.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glDisable(GL_DEPTH_TEST);
  glLineWidth(2.0f);
  glBegin(GL_LINE_LOOP);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -6.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glLineWidth(1.0f);
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // display lists for the shadows of the glyphs
  glNewList(mDisplayLists + 10, GL_COMPILE);<commit_msg>Fixed a bug in drawing of the unfilled arrow heads. Added a list of things that still need to be done. Only some of those are crucial for the release.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/layoutUI/CQGLNetworkPainter.cpp,v $
//   $Revision: 1.140 $
//   $Name:  $
//   $Author: gauges $
//   $Date: 2008/10/04 08:13:45 $
// End CVS Header

// Copyright (C) 2008 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by <NAME>, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <qstring.h>
#include <qbitmap.h>
#include <qpainter.h>
#include <qrect.h>
#include <qpoint.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qsize.h>
#include <qcolor.h>
#include <qtimer.h>
#include <qcanvas.h>

#include <qfontinfo.h>
#include <qfontdatabase.h>

#include <iostream>
#include <limits>
#include <math.h>
#include <float.h>
#include <utility>

#include "copasi/utilities/COutputHandler.h"

#include "copasi.h"

#include "FontChooser.h"

#if (defined WIN32 && !defined log2)
C_FLOAT64 log2(const C_FLOAT64 & __x)
{return log(__x) / log(2.0);}
#endif // WIN32

#include "CQGLNetworkPainter.h"
#include "CQLayoutMainWindow.h"

#include "UI/qtUtilities.h"
#include "layout/CLayout.h"
#include "utilities/CCopasiVector.h"
#include "layoutUI/CVisParameters.h"
#include "layoutUI/CDataEntity.h"
#include "layoutUI/BezierCurve.h"

// TODO check why zooming from the menu doesn't work any more
//
// TODO make sure that an animation is stopped if the layout window is closed.
//
// TODO check why the arrow heads are off when switching back from size
// animation to rectangular view
//
// TODO fix the bug in color animation mode if species are deactivated
//
// TODO implement the possibility to make screenshots of the visible area as
// well as the whole network and let the user choose the resolution
//
// TODO improve zooming (no clue how to do that best)
//
// TODO fix arrow positioning problems in size animation

// TODO change the text rendering or the texture creation. Right now it seems
// to work reasonably well under Mac OS X, but under Linux it doesn't.

// TODO Antialias Nodes and arrowheads, right now it looks as if only the edges
// do get antialiasing

// below species and speciesreference
const double CQGLNetworkPainter::COMPARTMENT_DEPTH = 0.001;
const double CQGLNetworkPainter::COMPARTMENT_SHADOW_DEPTH = 0.0009;
const double CQGLNetworkPainter::COMPARTMENT_FRAME_DEPTH = 0.0011;

const double CQGLNetworkPainter::SPECIES_DEPTH = 0.005;
const double CQGLNetworkPainter::SPECIES_SHADOW_DEPTH = 0.0049;
const double CQGLNetworkPainter::SPECIES_FRAME_DEPTH = 0.0051;

//below species
const double CQGLNetworkPainter::SPECIESREFERENCE_DEPTH = 0.003;

const GLfloat CQGLNetworkPainter::MIRROR_X[] =
  {
    1.0f, 0.0f, 0.0f, 0.0f
    , 0.0f, -1.0f, 0.0f, 0.0f
    , 0.0f, 0.0f, 1.0f, 0.0f
    , 0.0f, 0.0f, 0.0f, 1.0f
  };

const GLfloat CQGLNetworkPainter::MIRROR_Y[] =
  {
    -1.0f, 0.0f, 0.0f, 0.0f
    , 0.0f, 1.0f, 0.0f, 0.0f
    , 0.0f, 0.0f, 1.0f, 0.0f
    , 0.0f, 0.0f, 0.0f, 1.0f
  };

CQGLNetworkPainter::CQGLNetworkPainter(const QGLFormat& format, QWidget *parent, const char *name)
    : QGLWidget(format, parent, name)
{
  initializeGraphPainter(parent);
}

CQGLNetworkPainter::~CQGLNetworkPainter()
{
  std::map<std::string, RGTextureSpec*>::iterator it = labelTextureMap.begin(), endit = labelTextureMap.end();
  while (it != endit)
    {
      delete[] it->second->textureData;
      delete it->second;
      ++it;
    }
  // delete the node display list
  glDeleteLists(this->mDisplayLists, 17);
}

void CQGLNetworkPainter::initializeDisplayLists()
{
  glClearColor(mBackgroundColor[0], mBackgroundColor[1], mBackgroundColor[2], mBackgroundColor[3]);
  // convert the node into a display list that is created once and call once
  // for each node.
  // this might safe some cpu cycles, especially when the nodes get more fancy.
  this->mDisplayLists = glGenLists(17);
  // this list is for the rectangular nodes
  GLfloat compartmentColor_080[] = {mCompartmentColor[0] + (1.0f - mCompartmentColor[0]) * 0.8f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1]) * 0.8f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2]) * 0.8f};
  GLfloat speciesColor_080[] = {mSpeciesColor[0] + (1.0f - mSpeciesColor[0]) * 0.8f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1]) * 0.8f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2]) * 0.8f};
  glNewList(mDisplayLists, GL_COMPILE);
  // approximate a quarter circle by a triangle fan with 3 triangles
  glBegin(GL_TRIANGLE_FAN);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.0f, 0.4f, COMPARTMENT_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glColor3f(mCompartmentColor[0] + (1.0f - mCompartmentColor[0])*0.9f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1])*0.9f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2])*0.9f); // 90% value
  glVertex3f(0.05f, 0.4866f, COMPARTMENT_DEPTH);
  glColor3f(mCompartmentColor[0] + (1.0f - mCompartmentColor[0])*0.973f, mCompartmentColor[1] + (1.0f - mCompartmentColor[1])*0.973f, mCompartmentColor[2] + (1.0f - mCompartmentColor[2])*0.973f);  // 97.32% value
  glVertex3f(0.0866f, 0.45f, COMPARTMENT_DEPTH);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(compartmentColor_080);
  glVertex3f(0.0f, 0.4f, COMPARTMENT_DEPTH);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_DEPTH);
  glColor3fv(mCompartmentColor);
  glVertex3f(0.1f, 0.0f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the line strip a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINE_STRIP);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.05f, 0.4866f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.0866f, 0.45f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.1f, 0.4f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.1f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // now copy the first call list and mirror the copy at the x-axis
  glNewList(mDisplayLists + 1, GL_COMPILE);
  glPushMatrix();
  glTranslatef(0.0f, 0.5f, 0.0f);
  glCallList(mDisplayLists);
  // mirror transformation
  glMultMatrixf(MIRROR_X);
  glCallList(mDisplayLists);
  glPopMatrix();
  glEndList();

  // next list is the center piece for the compartment glyph
  glNewList(mDisplayLists + 2, GL_COMPILE);
  glBegin(GL_POLYGON);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 1.0f, COMPARTMENT_DEPTH);
  glVertex3f(1.0f, 1.0f, COMPARTMENT_DEPTH);
  glColor3fv(mCompartmentColor);
  glVertex3f(1.0f, 0.5f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(mCompartmentColor);
  glVertex3f(0.0f, 0.5f, COMPARTMENT_DEPTH);
  glVertex3f(1.0f, 0.5f, COMPARTMENT_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(1.0f, 0.0f, COMPARTMENT_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the lines  a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINES);
  glVertex3f(0.0f, 1.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(1.0f, 1.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(0.0f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glVertex3f(1.0f, 0.0f, COMPARTMENT_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // call lists for the species nodes
  glNewList(mDisplayLists + 3, GL_COMPILE);
  // approximate a quarter circle by a triangle fan with 3 triangles
  glBegin(GL_TRIANGLE_FAN);
  glColor3fv(speciesColor_080);
  glVertex3f(0.0f, 0.4f, SPECIES_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glColor3f(mSpeciesColor[0] + (1.0f - mSpeciesColor[0])*0.9f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1])*0.9f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2])*0.9f); // 90% value
  glVertex3f(0.05f, 0.4866f, SPECIES_DEPTH);
  glColor3f(mSpeciesColor[0] + (1.0f - mSpeciesColor[0])*0.973f, mSpeciesColor[1] + (1.0f - mSpeciesColor[1])*0.973f, mSpeciesColor[2] + (1.0f - mSpeciesColor[2])*0.973f);  // 97.32% value
  glVertex3f(0.0866f, 0.45f, SPECIES_DEPTH);
  glColor3fv(speciesColor_080);
  glVertex3f(0.1f, 0.4f, SPECIES_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(speciesColor_080);
  glVertex3f(0.0f, 0.4f, SPECIES_DEPTH);
  glVertex3f(0.1f, 0.4f, SPECIES_DEPTH);
  glColor4fv(mSpeciesColor);
  glVertex3f(0.1f, 0.0f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the line strip a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINE_STRIP);
  glVertex3f(0.0f, 0.5f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.05f, 0.4866f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.0866f, 0.45f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.1f, 0.4f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.1f, 0.0f, SPECIES_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // now copy the first call list and mirror the copy at the x-axis
  glNewList(mDisplayLists + 4, GL_COMPILE);
  glPushMatrix();
  glTranslatef(0.0f, 0.5f, 0.0f);
  glCallList(mDisplayLists + 3);
  // mirror transformation
  glMultMatrixf(MIRROR_X);
  glCallList(mDisplayLists + 3);
  glPopMatrix();
  glEndList();

  // next list is the center piece for the species glyph
  glNewList(mDisplayLists + 5, GL_COMPILE);
  glBegin(GL_POLYGON);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(0.0f, 1.0f, SPECIES_DEPTH);
  glVertex3f(1.0f, 1.0f, SPECIES_DEPTH);
  glColor3fv(mSpeciesColor);
  glVertex3f(1.0f, 0.5f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glEnd();
  glBegin(GL_POLYGON);
  glColor3fv(mSpeciesColor);
  glVertex3f(0.0f, 0.5f, SPECIES_DEPTH);
  glVertex3f(1.0f, 0.5f, SPECIES_DEPTH);
  glColor3f(1.0f, 1.0f, 1.0f);
  glVertex3f(1.0f, 0.0f, SPECIES_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_DEPTH);
  glEnd();
  glColor4fv(mFrameColor);
  glLineWidth(1.0f);
  // raise the lines  a bit to circumvent clipping errors
  glDisable(GL_DEPTH_TEST);
  glBegin(GL_LINES);
  glVertex3f(0.0f, 1.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(1.0f, 1.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(0.0f, 0.0f, SPECIES_FRAME_DEPTH);
  glVertex3f(1.0f, 0.0f, SPECIES_FRAME_DEPTH);
  glEnd();
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // display lists for arrow heads (try to be SBGN like)

  // head for stimulation (unfilled arrow)
  glNewList(mDisplayLists + 6, GL_COMPILE);
  glColor4fv(mBackgroundColor);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glDisable(GL_DEPTH_TEST);
  glLineWidth(2.0f);
  glColor4fv(mSpeciesReferenceColor);
  glBegin(GL_LINE_LOOP);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glLineWidth(1.0f);
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // head for transition (filled arrow head)
  glNewList(mDisplayLists + 7, GL_COMPILE);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -5.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glEndList();

  // head for inhibition (perpendicular bar)
  glNewList(mDisplayLists + 8, GL_COMPILE);
  glBegin(GL_POLYGON);
  glVertex3f(-3.0f, 0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(3.0f, 0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(3.0f, -0.5f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-3.0f, -0.5f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glEndList();

  // head for modulation (unfilled diamond)
  glNewList(mDisplayLists + 9, GL_COMPILE);
  glColor4fv(mBackgroundColor);
  glBegin(GL_POLYGON);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -6.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glDisable(GL_DEPTH_TEST);
  glColor4fv(mSpeciesReferenceColor);
  glLineWidth(2.0f);
  glBegin(GL_LINE_LOOP);
  glVertex3f(0.0f, 0.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(0.0f, -6.0f, SPECIESREFERENCE_DEPTH);
  glVertex3f(-2.0f, -3.0f, SPECIESREFERENCE_DEPTH);
  glEnd();
  glLineWidth(1.0f);
  glEnable(GL_DEPTH_TEST);
  glEndList();

  // display lists for the shadows of the glyphs
  glNewList(mDisplayLists + 10, GL_COMPILE);
{'fraction_non_alphanumeric': 0.14028705073361852, 'fraction_numerical': 0.06572582257226242, 'mean_word_length': 4.674682395644283, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3504139', 'n_tokens_mistral': 11768, 'n_tokens_neox': 10937, 'n_words': 1990}