#include <openbabel/babelconfig.h>
#include <openbabel/obmolecformat.h>
#include <openbabel/mol.h>
#include <openbabel/atom.h>
#include <openbabel/bond.h>
#include <openbabel/elements.h>
#include <openbabel/data.h>
#include <cstdlib>
using namespace std;
namespace OpenBabel
{
class AlchemyFormat : public OBMoleculeFormat
{
public:
AlchemyFormat()
{
OBConversion::RegisterFormat("alc",this, "chemical/x-alchemy");
}
virtual const char* Description() {
return
"Alchemy format\n"
"No comments yet\n";
};
virtual const char* SpecificationURL()
{ return "";};
virtual const char* GetMIMEType()
{ return "chemical/x-alchemy"; };
virtual unsigned int Flags()
{
return READONEONLY | WRITEONEONLY;
};
virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
};
AlchemyFormat theAlchemyFormat;
bool AlchemyFormat::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();
int i;
int natoms = 0, nbonds = 0;
char buffer[BUFF_SIZE];
ifs.getline(buffer,BUFF_SIZE);
sscanf(buffer," %d %*s %d", &natoms, &nbonds);
if (!natoms)
{
ifs.getline(buffer,BUFF_SIZE);
sscanf(buffer," %d %*s %d", &natoms, &nbonds);
if (!natoms)
return(false);
}
mol.ReserveAtoms(natoms);
mol.BeginModify();
ttab.SetFromType("ALC");
string str;
double x,y,z;
OBAtom *atom;
vector<string> vs;
for (i = 1; i <= natoms; i ++)
{
if (!ifs.getline(buffer,BUFF_SIZE))
return(false);
tokenize(vs,buffer);
if (vs.size() < 5)
return(false);
atom = mol.NewAtom();
x = atof((char*)vs[2].c_str());
y = atof((char*)vs[3].c_str());
z = atof((char*)vs[4].c_str());
atom->SetVector(x,y,z);
ttab.SetToType("ATN");
ttab.Translate(str,vs[1]);
atom->SetAtomicNum(atoi(str.c_str()));
ttab.SetToType("INT");
ttab.Translate(str,vs[1]);
atom->SetType(str);
}
char bobuf[100];
string bostr;
int bgn,end,order;
for (i = 0; i < nbonds; i++)
{
if (!ifs.getline(buffer,BUFF_SIZE))
return(false);
sscanf(buffer," %*d%d%d%99s",&bgn,&end,bobuf);
bostr = bobuf;
order = 1;
if (bostr == "DOUBLE")
order = 2;
else if (bostr == "TRIPLE")
order = 3;
else if (bostr == "AROMATIC")
order = 5;
mol.AddBond(bgn,end,order);
}
std::streampos ipos;
do
{
ipos = ifs.tellg();
ifs.getline(buffer,BUFF_SIZE);
}
while(strlen(buffer) == 0 && !ifs.eof() );
ifs.seekg(ipos);
mol.EndModify();
mol.SetTitle(title);
return(true);
}
bool AlchemyFormat::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];
char bond_string[10];
snprintf(buffer, BUFF_SIZE, "%5d ATOMS, %5d BONDS, 0 CHARGES",
mol.NumAtoms(),
mol.NumBonds());
ofs << buffer << endl;
OBAtom *atom;
string str,str1;
for(i = 1;i <= mol.NumAtoms(); i++)
{
atom = mol.GetAtom(i);
str = atom->GetType();
ttab.SetFromType("INT");
ttab.SetToType("ALC");
ttab.Translate(str1,str);
snprintf(buffer, BUFF_SIZE, "%5d %-6s%8.4f %8.4f %8.4f 0.0000",
i,
(char*)str1.c_str(),
atom->GetX(),
atom->GetY(),
atom->GetZ());
ofs << buffer << endl;
}
OBBond *bond;
vector<OBBond*>::iterator j;
for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j))
{
switch(bond->GetBondOrder())
{
case 1 :
strcpy(bond_string,"SINGLE");
break;
case 2 :
strcpy(bond_string,"DOUBLE");
break;
case 3 :
strcpy(bond_string,"TRIPLE");
break;
case 5 :
strcpy(bond_string,"AROMATIC");
break;
default :
strcpy(bond_string,"SINGLE");
}
snprintf(buffer, BUFF_SIZE, "%5d %4d %4d %s",
bond->GetIdx()+1,
bond->GetBeginAtomIdx(),
bond->GetEndAtomIdx(),
bond_string);
ofs << buffer << endl;
}
return(true);
}
}