Logo Search packages:      
Sourcecode: v-sim version File versions  Download package

ob_basic.cpp


#include <openbabel/obconversion.h>
#include <openbabel/obmolecformat.h>
#include <openbabel/mol.h>
#include <openbabel/math/matrix3x3.h>
#include <openbabel/math/vector3.h>

#include <visu_tools.h>
#include <renderingMethods/renderingAtomic.h>
#include <coreTools/toolFileFormat.h>
#include <coreTools/toolMatrix.h>
#include <visu_elements.h>
#include <visu_data.h>

using namespace OpenBabel;

extern "C"
{
  gboolean obloaderInit();
  const char* obloaderGet_description();
  const char* obloaderGet_authors();
  const char* obloaderGet_icon();
}

#define OPENBABEL_DESCRIPTION _("<span size=\"smaller\">" \
                        "This plug-in wraps the <b>OpenBabel</b>\n" \
                        "library (visit the home page at URL\n" \
                        "<span color=\"blue\"><u>http://openbabel.sourceforge.net</u></span>)</span>.")
#define OPENBABEL_AUTHORS     _("Caliste Damien:\n   wrapper.")

/* Local variables. */
static gchar *iconPath;

/* Local methods. */
static gboolean loadOpenBabelFile(VisuData *data, const gchar* filename,
                          FileFormat *format, GError **error);

/* Required methods for a loadable module. */
gboolean obloaderInit()
{
  RenderingFormatLoad* meth;
  char *type[] = {(char*)0};

  DBG_fprintf(stderr, "Openbabel : loading plug-in 'openbabel'...\n");

  meth = (RenderingFormatLoad*)g_malloc(sizeof(RenderingFormatLoad));
  meth->name = "OpenBabel wrapper";
  meth->fmt = fileFormatNew(_("OpenBabel known formats"), type);
  if (!meth->fmt)
    g_error("Can't initialize the OpenBabel loading method, aborting...\n");
  meth->priority = 75;
  meth->load = loadOpenBabelFile;
  renderingAtomicAdd_loadMethod(meth);

  iconPath = g_build_filename(v_sim_pixmaps_dir, "openbabel.png", NULL);

  return TRUE;
}

const char* obloaderGet_description()
{
  return OPENBABEL_DESCRIPTION;
}

const char* obloaderGet_authors()
{
  return OPENBABEL_AUTHORS;
}

const char* obloaderGet_icon()
{
  return (char*)iconPath;
}


static void addNode(GList **lst, OpenBabel::OBAtom *atom)
{
  char *ele;
  GList *tmplst;
  GList *lstatom;
  gboolean found;

  ele = atom->GetType();

  /* Look for type ele in lst. */
  found = FALSE;
  tmplst = *lst;
  while (tmplst && !found)
    {
      lstatom = (GList*)tmplst->data;
      if ( !strcmp(((OpenBabel::OBAtom*)lstatom->data)->GetType(), ele) )
      {
//      fprintf(stderr, "one node for element '%s'\n", ele);
        lstatom = g_list_prepend(lstatom, (gpointer)atom);
        tmplst->data = lstatom;
        found = TRUE;
      }
      tmplst = g_list_next(tmplst);
    }
  if (!found)
    {
//       fprintf(stderr, "one element '%s'\n", ele);
      lstatom = (GList*)0;
      lstatom = g_list_prepend(lstatom, (gpointer)atom);
      *lst = g_list_prepend(*lst, lstatom);
    }
}

static gboolean loadOpenBabelFile(VisuData *data, const gchar* filename,
                          FileFormat *format, GError **error)
{
  OpenBabel::OBMol *mol;
  OpenBabel::OBFormat *pFormat, *xyzFormat;
  bool res;
  gboolean res2;
  std::ifstream fin(filename);
  std::istream* pIn = &fin;
  OpenBabel::OBConversion conv(pIn, NULL);
  GList *allNodes, *lstatom, *tmplst;
  int ok, i, j;
  VisuElement **types, *visuele;
  int *nattyp;
  int ntype;
  char *ele;
  OpenBabel::OBUnitCell *uc;
  double rprimdFull[9], rprimd[3][3];
  double xu, yu, zu;
  double xMin, yMin, zMin, xMax, yMax, zMax;
  float boxGeometry[6];
  float translation[3];
  gchar *infoUTF8;
  double vect[3];

  g_return_val_if_fail(error && *error == (GError*)0, FALSE);
  g_return_val_if_fail(data && filename, FALSE);

  /* Create a new OpenBabel object. */
  mol = new OpenBabel::OBMol;

  /* Try to guess the file format. */
  DBG_fprintf(stderr, "Open Babel : try to guess the file format of '%s'.\n", filename);
  pFormat = conv.FormatFromExt(filename);
  if (!pFormat)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                     _("'%s' doesn't any file format."), filename);
      fin.close();
      return FALSE;
    }
  if ( pFormat->Flags() & NOTREADABLE )
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                     _("format of '%s' is not a readable one."), filename);
      fin.close();
      return FALSE;
    }
  /* Exclude the xyz file format since V_Sim handles it natively. */
  xyzFormat = conv.FindFormat("xyz");
  if (xyzFormat == pFormat)
    {
      DBG_fprintf(stderr, "OpenBabel : skip XYZ format.\n");
      fin.close();
      return FALSE;
    }

  DBG_fprintf(stderr, " | set format %p.\n", (gpointer)pFormat);
  DBG_fprintf(stderr, " | format description\n%s\n", pFormat->Description());
  conv.SetInFormat(pFormat);

  /* Read the file. */
  DBG_fprintf(stderr, "Open Babel : read the file.\n");
  res = conv.Read(mol);
  fin.close();
  if (!res)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                     _("The given file doesn't match the format '%s'."),
                     format->description);
      return FALSE;
    }

  /* Store if the file is periodic or not. */
  uc = (OBUnitCell*)mol->GetData(OBGenericDataType::UnitCell);
  if (uc)
    {
      DBG_fprintf(stderr, "OpenBabel : file has periodic conditions.\n");
      uc->GetCellMatrix().GetArray(rprimdFull);
      for (i = 0; i < 3; i++)
      for (j = 0; j < 3; j++)
        rprimd[i][j] = rprimdFull[i * 3 + j];
      res2 = matrix_reducePrimitiveVectors(boxGeometry, rprimd);
      if (!res2)
      {
        *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                         _("The cell is not well formed (basis is not 3D)."));
        return FALSE;
      }
      visuDataSet_boxGeometry(data, boxGeometry, TRUE);
      uc->GetOffset().Get(vect);
    }
  else
    {
      DBG_fprintf(stderr, "OpenBabel : file has no periodic conditions.\n");
      for (i = 0; i < 3; i++)
      vect[i] = 0.;
    }

  DBG_fprintf(stderr, "OpenBabel : first pass to find Elements.\n");
  allNodes = (GList*)0;
  FOR_ATOMS_OF_MOL(a,mol)
    {
      addNode(&allNodes, &(*a));
    }
  DBG_fprintf(stderr, "OpenBabel : count nodes.\n");
  /* Allocate the space for the nodes. */
  ntype = g_list_length(allNodes);
  types = (VisuElement**)g_malloc(sizeof(VisuElement*) * ntype);
  nattyp = (int*)g_malloc(sizeof(int) * ntype);
  /* Get the visuelements. */
  i = 0;
  tmplst = allNodes;
  while (tmplst)
    {
      lstatom = (GList*)tmplst->data;
      ele = ((OpenBabel::OBAtom*)lstatom->data)->GetType();
      types[i] = visuElementGet_fromName(ele);
      if (!types[i])
      {
        types[i] = visuElementNewWithName(ele);
        ok = visuElementAdd(types[i]);
      }
      nattyp[i] = g_list_length(lstatom);
      g_list_free(lstatom);
      DBG_fprintf(stderr, " | '%s' : %d.\n", types[i]->name, nattyp[i]);
      tmplst = g_list_next(tmplst);
      i += 1;
    }
  g_list_free(allNodes);
  
  /* Allocate space in the given visudata. */
  ok = visuDataSet_population(data, ntype, nattyp, types);
  if (!ok)
    g_error("Can't store the nodes in the VisuData object.");
  free(nattyp);
  free(types);

  /* Stores coordinates. */
  /* Try to find a box containing all nodes. */
  xMin = 1e5;
  yMin = 1e5;
  zMin = 1e5;
  xMax = -1e5;
  yMax = -1e5;
  zMax = -1e5;
  i = 0;
  FOR_ATOMS_OF_MOL(a,mol)
    {
      visuele = visuElementGet_fromName(a->GetType());
      xu = a->GetX() + vect[0];
      yu = a->GetY() + vect[1];
      zu = a->GetZ() + vect[2];
      visuDataAdd_VisuElement(data, visuele, xu, yu, zu, i);
      if (!uc)
      {
        if (xu < xMin)
          xMin = xu;
        if (yu < yMin)
          yMin = yu;
        if (zu < zMin)
          zMin = zu;
        if (xu > xMax)
          xMax = xu;
        if (yu > yMax)
          yMax = yu;
        if (zu > zMax)
          zMax = zu;
      }
      i += 1;
    }

  if (!uc)
    {
      DBG_fprintf(stderr, "OpenBabel : the elements are in [%f, %f]x[%f, %f]x[%f, %f].\n",
              xMin, xMax, yMin, yMax, zMin, zMax);
      boxGeometry[0] = xMax - xMin;
      boxGeometry[1] = 0.;
      boxGeometry[2] = yMax - yMin;
      boxGeometry[3] = 0.;
      boxGeometry[4] = 0.;
      boxGeometry[5] = zMax - zMin;
      visuDataSet_boxGeometry(data, boxGeometry, FALSE);

      translation[0] = -xMin;
      translation[1] = -yMin;
      translation[2] = -zMin;
      visuDataSet_XYZtranslation(data, translation);
    }

  /* Set the commentary. */
  if (mol->GetTitle())
    {
      infoUTF8 = getStringInUTF8(mol->GetTitle());
      visuDataSet_fileCommentary(data, infoUTF8);
      g_free(infoUTF8);
    }
  
  return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index