#include #include #include #include #include #include #include #include #include #include #include using namespace OpenBabel; extern "C" { gboolean obloaderInit(); const char* obloaderGet_description(); const char* obloaderGet_authors(); const char* obloaderGet_icon(); } #define OPENBABEL_DESCRIPTION _("" \ "This plug-in wraps the OpenBabel\n" \ "library (visit the home page at URL\n" \ "http://openbabel.sourceforge.net).") #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; }