#include <openbabel/babelconfig.h>
#include <openbabel/obmolecformat.h>
#include <openbabel/mol.h>
#include <openbabel/atom.h>
#include <openbabel/elements.h>
#include <cstdlib>
using namespace std;
namespace OpenBabel
{
class ViewMolFormat : public OBMoleculeFormat
{
public:
ViewMolFormat()
{
OBConversion::RegisterFormat("vmol",this);
}
virtual const char* Description() {
return
"ViewMol format\n"
"Read Options e.g. -as\n"
" s Output single bonds only\n"
" b Disable bonding entirely\n\n";
};
virtual const char* SpecificationURL() { return "http://viewmol.sourceforge.net/"; };
virtual unsigned int Flags()
{
return READONEONLY | WRITEONEONLY;
};
virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
};
ViewMolFormat theViewMolFormat;
bool ViewMolFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
{
OBMol* pmol = pOb->CastAndClear<OBMol>();
if (pmol == nullptr)
return false;
istream &ifs = *pConv->GetInStream();
OBMol &mol = *pmol;
const char* title = pConv->GetTitle();
char buffer[BUFF_SIZE];
OBAtom *atom;
double x,y,z, border;
double factor = 1.0;
int bgn, end, order;
vector<string> vs;
bool foundTitle = false;
bool foundBonds = false;
mol.Clear();
mol.BeginModify();
ifs.getline(buffer,BUFF_SIZE);
while (ifs.peek() != EOF && ifs.good())
{
if (strstr(buffer, "$title") != nullptr)
{
if (!ifs.getline(buffer,BUFF_SIZE))
return (false);
mol.SetTitle(buffer);
foundTitle = true;
ifs.getline(buffer,BUFF_SIZE);
}
else if (strstr(buffer, "$coord") != nullptr)
{
tokenize(vs,buffer);
if (vs.size() == 2)
factor = atof((char*)vs[1].c_str()); while (ifs.getline(buffer,BUFF_SIZE))
{
if (buffer[0] == '$')
break;
tokenize(vs,buffer);
if (vs.size() != 4)
break;
atom = mol.NewAtom();
x = atof((char*)vs[0].c_str()) * factor;
y = atof((char*)vs[1].c_str()) * factor;
z = atof((char*)vs[2].c_str()) * factor;
atom->SetVector(x,y,z); atom->SetAtomicNum(OBElements::GetAtomicNum(vs[3].c_str()));
}
}
else if (strstr(buffer, "$bonds") != nullptr)
{
foundBonds = true;
while (ifs.getline(buffer,BUFF_SIZE))
{
if (buffer[0] == '$')
break;
sscanf(buffer,"%d %d %lf",&bgn,&end, &border);
if (border > 1.0)
order = int(border);
else
order = 1;
mol.AddBond(bgn+1,end+1,order);
}
}
else if (strstr(buffer, "$end") != nullptr)
break;
else ifs.getline(buffer,BUFF_SIZE);
}
if (!foundBonds)
{
if (!pConv->IsOption("b",OBConversion::INOPTIONS))
mol.ConnectTheDots();
if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
mol.PerceiveBondOrders();
}
mol.EndModify();
if (!foundTitle)
mol.SetTitle(title);
return(true);
}
bool ViewMolFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
{
OBMol* pmol = dynamic_cast<OBMol*>(pOb);
if (pmol == nullptr)
return false;
ostream &ofs = *pConv->GetOutStream();
OBMol &mol = *pmol;
unsigned int i;
char buffer[BUFF_SIZE];
if (strlen(mol.GetTitle()) > 0)
ofs << "$title" << endl << mol.GetTitle() << endl;
ofs << "$coord 1.0" << endl;
OBAtom *atom;
for(i = 1;i <= mol.NumAtoms(); i++)
{
atom = mol.GetAtom(i);
snprintf(buffer, BUFF_SIZE, "%22.14f%22.14f%22.14f %s",
atom->GetX(),
atom->GetY(),
atom->GetZ(),
OBElements::GetSymbol(atom->GetAtomicNum()));
ofs << buffer << endl;
}
ofs << "$end" << endl;
return(true);
}
}