static unsigned int FindRingAtomsAndBonds2(OBMol &mol) { mol.SetRingAtomsAndBondsPerceived(); // mol.SetFlag(OB_RINGFLAGS_MOL); mol.SetClosureBondsPerceived(); // mol.SetFlag(OB_CLOSURE_MOL); unsigned int bsize = mol.NumBonds()+1; unsigned char *bvisit = (unsigned char*)malloc(bsize); memset(bvisit,0,bsize); unsigned int acount = mol.NumAtoms(); unsigned int asize = (unsigned int)((acount+1)*sizeof(int)); int *avisit = (int*)malloc(asize); memset(avisit,0,asize); unsigned int frj = 0; for(unsigned int i=1; i<=acount; i++ ) if(avisit[i] == 0) { avisit[i] = 1; OBAtom *atom = mol.GetAtom(i); FindRings(atom,avisit,bvisit,frj,1); } free(avisit); free(bvisit); return frj; }
void OBMol::FindRingAtomsAndBonds() { if (HasFlag(OB_RINGFLAGS_MOL)) return; SetFlag(OB_RINGFLAGS_MOL); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::FindRingAtomsAndBonds", obAuditMsg); OBBitVec avisit,bvisit; avisit.Resize(NumAtoms()+1); bvisit.Resize(NumAtoms()+1); vector<int> path; path.resize(NumAtoms()+1); for(unsigned int i=1; i<= NumAtoms(); i++ ) if(!avisit[i]) FindRings(*this,path,avisit,bvisit,i,0); }
static void FindRings(OBMol &mol,vector<int> &path,OBBitVec &avisit, OBBitVec &bvisit, int natom,int depth ) { OBAtom *atom; OBBond *bond; vector<OBBond*>::iterator k; // don't return if all atoms are visited // (For example, some atoms are in multiple rings!) -GRH if (avisit[natom]) { int j = depth-1; bond=mol.GetBond(path[j--]); bond->SetInRing(); while( j >= 0 ) { bond=mol.GetBond(path[j--]); bond->SetInRing(); (bond->GetBeginAtom())->SetInRing(); (bond->GetEndAtom())->SetInRing(); if(bond->GetBeginAtomIdx()==static_cast<unsigned int>(natom) || bond-> GetEndAtomIdx()==static_cast<unsigned int>(natom)) break; } } else { avisit.SetBitOn(natom); atom = mol.GetAtom(natom); for(bond = atom->BeginBond(k);bond;bond=atom->NextBond(k)) if( !bvisit[bond->GetIdx()]) { path[depth] = bond->GetIdx(); bvisit.SetBitOn(bond->GetIdx()); FindRings(mol,path,avisit,bvisit,bond->GetNbrAtomIdx(atom), depth+1); } } }
/* 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; }