bool OBBond::IsClosure() { OBMol *mol = (OBMol*)GetParent(); if (!mol) return(false); if (mol->HasClosureBondsPerceived()) return(HasFlag(OB_CLOSURE_BOND)); mol->SetClosureBondsPerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::PerceiveClosureBonds", obAuditMsg); OBBond *bond; OBAtom *atom,*nbr; OBBitVec uatoms,ubonds; vector<OBAtom*> curr,next; vector<OBAtom*>::iterator i; vector<OBBond*>::iterator j; uatoms.Resize(mol->NumAtoms()+1); ubonds.Resize(mol->NumAtoms()+1); for (;static_cast<unsigned int>(uatoms.CountBits()) < mol->NumAtoms();) { if (curr.empty()) for (atom = mol->BeginAtom(i);atom;atom = mol->NextAtom(i)) if (!uatoms[atom->GetIdx()]) { uatoms |= atom->GetIdx(); curr.push_back(atom); break; } for (;!curr.empty();) { for (i = curr.begin();i != curr.end();++i) for (nbr = ((OBAtom*)*i)->BeginNbrAtom(j);nbr;nbr = ((OBAtom*)*i)->NextNbrAtom(j)) if (!uatoms[nbr->GetIdx()]) { uatoms |= nbr->GetIdx(); ubonds |= (*j)->GetIdx(); next.push_back(nbr); } curr = next; next.clear(); } } for (bond = mol->BeginBond(j);bond;bond = mol->NextBond(j)) if (!ubonds[bond->GetIdx()]) bond->SetClosure(); return(HasFlag(OB_CLOSURE_BOND)); }
/* A recursive O(N) traversal of the molecule */ static int FindRings(OBAtom *atom, int *avisit, unsigned char *bvisit, unsigned int &frj, int depth) { OBBond *bond; int result = -1; vector<OBBond*>::iterator k; for(bond = atom->BeginBond(k);bond;bond=atom->NextBond(k)) { unsigned int bidx = bond->GetIdx(); if (bvisit[bidx] == 0) { bvisit[bidx] = 1; OBAtom *nbor = bond->GetNbrAtom(atom); unsigned int nidx = nbor->GetIdx(); int nvisit = avisit[nidx]; if (nvisit == 0) { avisit[nidx] = depth+1; nvisit = FindRings(nbor,avisit,bvisit,frj,depth+1); if (nvisit > 0) { if (nvisit <= depth) { bond->SetInRing(); if (result < 0 || nvisit < result) result = nvisit; } } } else { if (result < 0 || nvisit < result) result = nvisit; bond->SetClosure(); bond->SetInRing(); frj++; } } } if (result > 0 && result <= depth) atom->SetInRing(); return result; }