#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;
}
syntax highlighted by Code2HTML, v. 0.9.1