#include <openbabel/babelconfig.h>
#include <openbabel/math/matrix3x3.h>
#include <openbabel/obmolecformat.h>
#include <openbabel/mol.h>
#include <openbabel/atom.h>
#include <openbabel/elements.h>
#include <openbabel/generic.h>
#include <cstdlib>
using namespace std;
namespace OpenBabel
{
class ShelXFormat : public OBMoleculeFormat
{
public:
ShelXFormat()
{
OBConversion::RegisterFormat("res",this, "chemical/x-shelx");
OBConversion::RegisterFormat("ins",this, "chemical/x-shelx");
}
virtual const char* Description() {
return
"ShelX 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://shelx.uni-ac.gwdg.de/SHELX/";};
virtual const char* GetMIMEType()
{ return "chemical/x-shelx"; };
virtual unsigned int Flags()
{
return NOTWRITABLE;
};
virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
};
ShelXFormat theShelXFormat;
bool ShelXFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
{
OBMol* pmol = pOb->CastAndClear<OBMol>();
if (pmol == nullptr)
return false;
istream &ifs = *pConv->GetInStream();
OBMol &mol = *pmol;
mol.SetTitle( pConv->GetTitle());
char buffer[BUFF_SIZE];
double A,B,C,Alpha,Beta,Gamma;
matrix3x3 m;
ifs.getline(buffer,BUFF_SIZE);
mol.SetTitle(buffer);
while (ifs.getline(buffer,BUFF_SIZE) &&!EQn(buffer,"CELL",4))
;
if (!EQn(buffer,"CELL",4))
return(false);
vector<string> vs;
tokenize(vs,buffer," \n\t,");
if (vs.size() != 8)
return(false);
A = atof((char*)vs[2].c_str());
B = atof((char*)vs[3].c_str());
C = atof((char*)vs[4].c_str());
Alpha = atof((char*)vs[5].c_str());
Beta = atof((char*)vs[6].c_str());
Gamma = atof((char*)vs[7].c_str());
OBUnitCell *uc = new OBUnitCell;
uc->SetOrigin(fileformatInput);
uc->SetData(A, B, C, Alpha, Beta, Gamma);
mol.SetData(uc);
double x,y,z;
char type[16], *j;
OBAtom *atom;
vector3 v;
while (ifs.getline(buffer,BUFF_SIZE) &&!EQn(buffer,"FVAR",4))
;
mol.BeginModify();
while (ifs.getline(buffer,BUFF_SIZE) &&!EQn(buffer,"HKLF",4))
{
tokenize(vs,buffer," \n\t,");
if (vs.size() < 7)
continue;
atom = mol.NewAtom();
x = atof((char*)vs[2].c_str());
y = atof((char*)vs[3].c_str());
z = atof((char*)vs[4].c_str());
v.Set(x,y,z);
v = uc->FractionalToCartesian(v);
strncpy(type,vs[0].c_str(), sizeof(type));
type[sizeof(type) - 1] = '\0';
j = strpbrk(type, "0123456789");
j[0] = '\0';
atom->SetAtomicNum(OBElements::GetAtomicNum(type));
atom->SetVector(v);
if (vs.size() == 9)
ifs.getline(buffer,BUFF_SIZE);
}
if (!pConv->IsOption("b",OBConversion::INOPTIONS))
mol.ConnectTheDots();
if (!pConv->IsOption("s",OBConversion::INOPTIONS) && !pConv->IsOption("b",OBConversion::INOPTIONS))
mol.PerceiveBondOrders();
mol.EndModify();
return(true);
}
}