// $Id$ // // Copyright (C) 2001-2010 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license // which is included in the file license.txt, found at the root // of the RDKit source tree. // #include "Bond.h" #include "Atom.h" #include "ROMol.h" #include namespace RDKit { Bond::Bond() { initBond(); dp_props = new Dict(); }; Bond::Bond(BondType bT) { initBond(); d_bondType = bT; dp_props = new Dict(); }; Bond::Bond(const Bond &other) { // NOTE: we do *not* copy ownership! dp_mol = 0; d_bondType = other.d_bondType; d_beginAtomIdx = other.d_beginAtomIdx; d_endAtomIdx = other.d_endAtomIdx; d_dirTag = other.d_dirTag; d_stereo = other.d_stereo; if (other.dp_stereoAtoms) { dp_stereoAtoms = new INT_VECT(*other.dp_stereoAtoms); } else { dp_stereoAtoms = NULL; } df_isAromatic = other.df_isAromatic; df_isConjugated = other.df_isConjugated; d_index = other.d_index; if (other.dp_props) { dp_props = new Dict(*other.dp_props); } else { dp_props = new Dict(); } } Bond::~Bond() { delete dp_props; delete dp_stereoAtoms; } Bond &Bond::operator=(const Bond &other) { dp_mol = other.dp_mol; d_bondType = other.d_bondType; d_beginAtomIdx = other.d_beginAtomIdx; d_endAtomIdx = other.d_endAtomIdx; d_dirTag = other.d_dirTag; if (other.dp_stereoAtoms) { dp_stereoAtoms = new INT_VECT(*other.dp_stereoAtoms); } else { dp_stereoAtoms = NULL; } df_isAromatic = other.df_isAromatic; df_isConjugated = other.df_isConjugated; d_index = other.d_index; if (other.dp_props) { dp_props = new Dict(*other.dp_props); } else { dp_props = new Dict(); } return *this; } Bond *Bond::copy() const { Bond *res = new Bond(*this); return res; } void Bond::setOwningMol(ROMol *other) { // FIX: doesn't update topology dp_mol = other; } unsigned int Bond::getOtherAtomIdx(const unsigned int thisIdx) const { PRECONDITION(d_beginAtomIdx == thisIdx || d_endAtomIdx == thisIdx, "bad index"); if (d_beginAtomIdx == thisIdx) return d_endAtomIdx; else if (d_endAtomIdx == thisIdx) return d_beginAtomIdx; // we cannot actually get down here return 0; } void Bond::setBeginAtomIdx(unsigned int what) { if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms() - 1); d_beginAtomIdx = what; }; void Bond::setEndAtomIdx(unsigned int what) { if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms() - 1); d_endAtomIdx = what; }; void Bond::setBeginAtom(Atom *at) { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); setBeginAtomIdx(at->getIdx()); } void Bond::setBeginAtom(Atom::ATOM_SPTR at) { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); setBeginAtomIdx(at->getIdx()); } void Bond::setEndAtom(Atom *at) { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); setEndAtomIdx(at->getIdx()); } void Bond::setEndAtom(Atom::ATOM_SPTR at) { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); setEndAtomIdx(at->getIdx()); } Atom *Bond::getBeginAtom() const { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); return dp_mol->getAtomWithIdx(d_beginAtomIdx); }; Atom *Bond::getEndAtom() const { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); return dp_mol->getAtomWithIdx(d_endAtomIdx); }; Atom *Bond::getOtherAtom(Atom const *what) const { PRECONDITION(dp_mol != 0, "no owning molecule for bond"); return dp_mol->getAtomWithIdx(getOtherAtomIdx(what->getIdx())); }; double Bond::getBondTypeAsDouble() const { switch (getBondType()) { case UNSPECIFIED: return 0; break; case IONIC: return 0; break; case SINGLE: return 1; break; case DOUBLE: return 2; break; case TRIPLE: return 3; break; case QUADRUPLE: return 4; break; case QUINTUPLE: return 5; break; case HEXTUPLE: return 6; break; case ONEANDAHALF: return 1.5; break; case TWOANDAHALF: return 2.5; break; case THREEANDAHALF: return 3.5; break; case FOURANDAHALF: return 4.5; break; case FIVEANDAHALF: return 5.5; break; case AROMATIC: return 1.5; break; case DATIVEONE: return 1.0; break; // FIX: this should probably be different case DATIVE: return 1.0; break; // FIX: again probably wrong case ZERO: return 0; break; default: UNDER_CONSTRUCTION("Bad bond type"); } } double Bond::getValenceContrib(Atom::ATOM_SPTR at) const { return getValenceContrib(at.get()); } double Bond::getValenceContrib(const Atom *atom) const { switch (getBondType()) { case UNSPECIFIED: return 0; break; case IONIC: return 0; break; case SINGLE: return 1; break; case DOUBLE: return 2; break; case TRIPLE: return 3; break; case QUADRUPLE: return 4; break; case QUINTUPLE: return 5; break; case HEXTUPLE: return 6; break; case ONEANDAHALF: return 1.5; break; case TWOANDAHALF: return 2.5; break; case THREEANDAHALF: return 3.5; break; case FOURANDAHALF: return 4.5; break; case FIVEANDAHALF: return 5.5; break; case AROMATIC: return 1.5; break; case DATIVEONE: if (atom->getIdx() == getEndAtomIdx()) return 1.0; else return 0.0; break; case DATIVE: if (atom->getIdx() == getEndAtomIdx()) return 1.0; else return 0.0; break; case ZERO: return 0; break; default: UNDER_CONSTRUCTION("Bad bond type"); } } void Bond::setQuery(QUERYBOND_QUERY *what) { // Bonds don't have queries at the moment because I have not // yet figured out what a good base query should be. // It would be nice to be able to do substructure searches // using molecules alone, so it'd be nice if we got this // issue resolved ASAP. RDUNUSED_PARAM(what); PRECONDITION(0, "plain bonds have no Query"); } Bond::QUERYBOND_QUERY *Bond::getQuery() const { PRECONDITION(0, "plain bonds have no Query"); return NULL; }; bool Bond::Match(Bond const *what) const { bool res; if (getBondType() == Bond::UNSPECIFIED || what->getBondType() == Bond::UNSPECIFIED) { res = true; } else { res = getBondType() == what->getBondType(); } return res; }; bool Bond::Match(const Bond::BOND_SPTR what) const { return Match(what.get()); }; void Bond::expandQuery(Bond::QUERYBOND_QUERY *what, Queries::CompositeQueryType how, bool maintainOrder) { RDUNUSED_PARAM(what); RDUNUSED_PARAM(how); RDUNUSED_PARAM(maintainOrder); PRECONDITION(0, "plain bonds have no query"); }; void Bond::initBond() { d_bondType = UNSPECIFIED; d_dirTag = NONE; d_stereo = STEREONONE; dp_mol = 0; d_beginAtomIdx = 0; d_endAtomIdx = 0; df_isAromatic = 0; d_index = 0; df_isConjugated = 0; dp_stereoAtoms = NULL; }; }; // end o' namespace std::ostream &operator<<(std::ostream &target, const RDKit::Bond &bond) { target << bond.getIdx() << " "; target << bond.getBeginAtomIdx() << "->" << bond.getEndAtomIdx(); target << " order: " << bond.getBondType(); if (bond.getBondDir()) target << " dir: " << bond.getBondDir(); if (bond.getStereo()) target << " stereo: " << bond.getStereo(); target << " conj?: " << bond.getIsConjugated(); target << " aromatic?: " << bond.getIsAromatic(); return target; }