mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-05 22:04:27 +08:00
458 lines
14 KiB
C++
458 lines
14 KiB
C++
//
|
|
// Copyright (C) 2001-2014 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.
|
|
//
|
|
#ifndef _RD_BOND_H
|
|
#define _RD_BOND_H
|
|
|
|
// std stuff
|
|
#include <iostream>
|
|
|
|
// Ours
|
|
// FIX: grn...
|
|
#include <Query/QueryObjects.h>
|
|
#include <RDGeneral/types.h>
|
|
#include <GraphMol/details.h>
|
|
#include <boost/foreach.hpp>
|
|
|
|
namespace RDKit{
|
|
class ROMol;
|
|
class RWMol;
|
|
class Atom;
|
|
typedef boost::shared_ptr<Atom> ATOM_SPTR;
|
|
|
|
//! class for representing a bond
|
|
/*!
|
|
|
|
<b>Notes:</b>
|
|
- many of the methods of Atom require that the Atom be associated
|
|
with a molecule (an ROMol).
|
|
- each Bond maintains a Dict of \c properties:
|
|
- Each \c property is keyed by name and can store an
|
|
arbitrary type.
|
|
- \c Properties can be marked as \c calculated, in which case
|
|
they will be cleared when the \c clearComputedProps() method
|
|
is called.
|
|
- Because they have no impact upon chemistry, all \c property
|
|
operations are \c const, this allows extra flexibility for
|
|
clients who need to store extra data on Bond objects.
|
|
|
|
*/
|
|
class Bond {
|
|
friend class RWMol;
|
|
friend class ROMol;
|
|
public:
|
|
typedef boost::shared_ptr<Bond> BOND_SPTR;
|
|
// FIX: grn...
|
|
typedef Queries::Query<int,Bond const *,true> QUERYBOND_QUERY;
|
|
|
|
//! the type of Bond
|
|
typedef enum {
|
|
UNSPECIFIED = 0,
|
|
SINGLE,
|
|
DOUBLE,
|
|
TRIPLE,
|
|
QUADRUPLE,
|
|
QUINTUPLE,
|
|
HEXTUPLE,
|
|
ONEANDAHALF,
|
|
TWOANDAHALF,
|
|
THREEANDAHALF,
|
|
FOURANDAHALF,
|
|
FIVEANDAHALF,
|
|
AROMATIC,
|
|
IONIC,
|
|
HYDROGEN,
|
|
THREECENTER,
|
|
DATIVEONE, //!< one-electron dative (e.g. from a C in a Cp ring to a metal)
|
|
DATIVE, //!< standard two-electron dative
|
|
DATIVEL, //!< standard two-electron dative
|
|
DATIVER, //!< standard two-electron dative
|
|
OTHER,
|
|
ZERO //!< Zero-order bond (from http://pubs.acs.org/doi/abs/10.1021/ci200488k)
|
|
} BondType;
|
|
|
|
//! the bond's direction (for chirality)
|
|
typedef enum {
|
|
NONE=0, //!< no special style
|
|
BEGINWEDGE, //!< wedged: narrow at begin
|
|
BEGINDASH, //!< dashed: narrow at begin
|
|
// FIX: this may not really be adequate
|
|
ENDDOWNRIGHT, //!< for cis/trans
|
|
ENDUPRIGHT, //!< ditto
|
|
EITHERDOUBLE, //!< a "crossed" double bond
|
|
UNKNOWN, //!< intentionally unspecified stereochemistry
|
|
} BondDir;
|
|
|
|
//! the nature of the bond's stereochem (for cis/trans)
|
|
typedef enum { // stereochemistry of double bonds
|
|
STEREONONE=0, // no special style
|
|
STEREOANY, // intentionally unspecified
|
|
// -- Put any true specifications about this point so
|
|
// that we can do comparisons like if(bond->getStereo()>Bond::STEREOANY)
|
|
STEREOZ, // Z double bond
|
|
STEREOE, // E double bond
|
|
} BondStereo;
|
|
|
|
Bond();
|
|
//! construct with a particular BondType
|
|
explicit Bond(BondType bT);
|
|
Bond(const Bond &other);
|
|
virtual ~Bond();
|
|
Bond &operator=(const Bond &other);
|
|
|
|
//! returns a copy
|
|
/*!
|
|
<b>Note:</b> the caller is responsible for <tt>delete</tt>ing
|
|
the returned pointer.
|
|
*/
|
|
virtual Bond *copy() const;
|
|
|
|
//! returns our \c bondType
|
|
BondType getBondType() const { return static_cast<BondType>(d_bondType); };
|
|
//! sets our \c bondType
|
|
void setBondType(BondType bT) { d_bondType = bT; };
|
|
//! \brief returns our \c bondType as a double
|
|
//! (e.g. SINGLE->1.0, AROMATIC->1.5, etc.)
|
|
double getBondTypeAsDouble() const;
|
|
|
|
//! returns our contribution to the explicit valence of an Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
double getValenceContrib(const Atom *at) const;
|
|
// \overload
|
|
double getValenceContrib(ATOM_SPTR at) const;
|
|
|
|
//! sets our \c isAromatic flag
|
|
void setIsAromatic( bool what ) { df_isAromatic = what; };
|
|
//! returns the status of our \c isAromatic flag
|
|
bool getIsAromatic() const { return df_isAromatic; };
|
|
|
|
//! sets our \c isConjugated flag
|
|
void setIsConjugated(bool what) {df_isConjugated = what;};
|
|
//! returns the status of our \c isConjugated flag
|
|
bool getIsConjugated() const {return df_isConjugated;};
|
|
|
|
//! returns a reference to the ROMol that owns this Bond
|
|
ROMol &getOwningMol() const { return *dp_mol; };
|
|
//! sets our owning molecule
|
|
void setOwningMol(ROMol *other);
|
|
//! sets our owning molecule
|
|
void setOwningMol(ROMol &other) {setOwningMol(&other);};
|
|
|
|
//! returns our index within the ROMol
|
|
/*!
|
|
<b>Notes:</b>
|
|
- this makes no sense if we do not have an owning molecule
|
|
|
|
*/
|
|
unsigned int getIdx() const {return d_index;};
|
|
//! sets our index within the ROMol
|
|
/*!
|
|
<b>Notes:</b>
|
|
- this makes no sense if we do not have an owning molecule
|
|
- the index should be <tt>< this->getOwningMol()->getNumBonds()</tt>
|
|
*/
|
|
void setIdx(unsigned int index) {d_index=index;};
|
|
|
|
//! returns the index of our begin Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- this makes no sense if we do not have an owning molecule
|
|
*/
|
|
unsigned int getBeginAtomIdx() const { return d_beginAtomIdx; };
|
|
|
|
//! returns the index of our end Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- this makes no sense if we do not have an owning molecule
|
|
*/
|
|
unsigned int getEndAtomIdx() const { return d_endAtomIdx; };
|
|
|
|
//! given the index of one Atom, returns the index of the other
|
|
/*!
|
|
<b>Notes:</b>
|
|
- this makes no sense if we do not have an owning molecule
|
|
*/
|
|
unsigned int getOtherAtomIdx(unsigned int thisIdx) const;
|
|
|
|
//! sets the index of our begin Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
void setBeginAtomIdx(unsigned int what);
|
|
//! sets the index of our end Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
void setEndAtomIdx(unsigned int what);
|
|
|
|
//! sets our begin Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
void setBeginAtom(Atom *at);
|
|
//! \overload
|
|
void setBeginAtom(ATOM_SPTR at);
|
|
//! sets our end Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
void setEndAtom(Atom *at);
|
|
//! \overload
|
|
void setEndAtom(ATOM_SPTR at);
|
|
|
|
|
|
//! returns a pointer to our begin Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
Atom *getBeginAtom() const;
|
|
//! returns a pointer to our end Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
Atom *getEndAtom() const;
|
|
//! returns a pointer to the other Atom
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
Atom *getOtherAtom(Atom const *what) const;
|
|
|
|
// ------------------------------------
|
|
// Please see the note in Atom.h for some explanation
|
|
// of these methods
|
|
// ------------------------------------
|
|
|
|
// This method can be used to distinguish query bonds from standard bonds
|
|
virtual bool hasQuery() const { return false; };
|
|
|
|
// FIX: the const crap here is all mucked up.
|
|
//! NOT CALLABLE
|
|
virtual void setQuery(QUERYBOND_QUERY *what);
|
|
//! NOT CALLABLE
|
|
virtual QUERYBOND_QUERY *getQuery() const;
|
|
|
|
//! NOT CALLABLE
|
|
virtual void expandQuery(QUERYBOND_QUERY *what,
|
|
Queries::CompositeQueryType how=Queries::COMPOSITE_AND,
|
|
bool maintainOrder=true);
|
|
|
|
//! returns whether or not we match the argument
|
|
/*!
|
|
<b>Notes:</b>
|
|
- for Bond objects, "match" means that either one of the Bonds
|
|
has \c bondType Bond::UNSPECIFIED or both Bonds have the
|
|
same \c bondType.
|
|
*/
|
|
virtual bool Match(Bond const *what) const;
|
|
//! \overload
|
|
virtual bool Match(const Bond::BOND_SPTR what) const;
|
|
|
|
//! sets our direction
|
|
void setBondDir(BondDir what) { d_dirTag = what; };
|
|
//! returns our direction
|
|
BondDir getBondDir() const { return static_cast<BondDir>(d_dirTag); };
|
|
|
|
//! sets our stereo code
|
|
void setStereo(BondStereo what) { d_stereo = what; };
|
|
//! returns our stereo code
|
|
BondStereo getStereo() const { return static_cast<BondStereo>(d_stereo); };
|
|
|
|
//! returns the indices of our stereo atoms
|
|
const INT_VECT &getStereoAtoms() const {
|
|
if(!dp_stereoAtoms){
|
|
const_cast<Bond *>(this)->dp_stereoAtoms = new INT_VECT();
|
|
}
|
|
return *dp_stereoAtoms;
|
|
};
|
|
//! \overload
|
|
INT_VECT &getStereoAtoms() {
|
|
if(!dp_stereoAtoms) dp_stereoAtoms = new INT_VECT();
|
|
return *dp_stereoAtoms;
|
|
};
|
|
|
|
// ------------------------------------
|
|
// Local Property Dict functionality
|
|
// FIX: at some point this stuff should go in a mixin class
|
|
// ------------------------------------
|
|
//! returns a list with the names of our \c properties
|
|
STR_VECT getPropList() const {
|
|
return dp_props->keys();
|
|
}
|
|
|
|
//! sets a \c property value
|
|
/*!
|
|
\param key the name under which the \c property should be stored.
|
|
If a \c property is already stored under this name, it will be
|
|
replaced.
|
|
\param val the value to be stored
|
|
\param computed (optional) allows the \c property to be flagged
|
|
\c computed.
|
|
*/
|
|
template <typename T>
|
|
void setProp(const char *key,T val, bool computed=false) const{
|
|
//if(!dp_props) dp_props = new Dict();
|
|
std::string what(key);
|
|
setProp(what,val, computed);
|
|
}
|
|
//! \overload
|
|
template <typename T>
|
|
void setProp(const std::string &key,T val, bool computed=false ) const{
|
|
//setProp(key.c_str(),val);
|
|
if (computed) {
|
|
STR_VECT compLst;
|
|
getPropIfPresent(detail::computedPropName, compLst);
|
|
if (std::find(compLst.begin(), compLst.end(), key) == compLst.end()) {
|
|
compLst.push_back(key);
|
|
dp_props->setVal(detail::computedPropName, compLst);
|
|
}
|
|
}
|
|
dp_props->setVal(key,val);
|
|
}
|
|
|
|
//! allows retrieval of a particular property value
|
|
/*!
|
|
|
|
\param key the name under which the \c property should be stored.
|
|
If a \c property is already stored under this name, it will be
|
|
replaced.
|
|
\param res a reference to the storage location for the value.
|
|
|
|
<b>Notes:</b>
|
|
- if no \c property with name \c key exists, a KeyErrorException will be thrown.
|
|
- the \c boost::lexical_cast machinery is used to attempt type conversions.
|
|
If this fails, a \c boost::bad_lexical_cast exception will be thrown.
|
|
|
|
*/
|
|
template <typename T>
|
|
void getProp(const char *key,T &res) const {
|
|
PRECONDITION(dp_props,"getProp called on empty property dict");
|
|
dp_props->getVal(key,res);
|
|
}
|
|
//! \overload
|
|
template <typename T>
|
|
void getProp(const std::string &key,T &res) const {
|
|
PRECONDITION(dp_props,"getProp called on empty property dict");
|
|
dp_props->getVal(key,res);
|
|
}
|
|
|
|
//! \Overload
|
|
template <typename T>
|
|
T getProp(const char *key) const {
|
|
return dp_props->getVal<T>(key);
|
|
}
|
|
//! \overload
|
|
template <typename T>
|
|
T getProp(const std::string &key) const {
|
|
return dp_props->getVal<T>(key);
|
|
}
|
|
|
|
//! returns whether or not we have a \c property with name \c key
|
|
//! and assigns the value if we do
|
|
|
|
template <typename T>
|
|
bool getPropIfPresent(const char *key,T &res) const {
|
|
return dp_props->getValIfPresent(key,res);
|
|
}
|
|
//! \overload
|
|
template <typename T>
|
|
bool getPropIfPresent(const std::string &key,T &res) const {
|
|
return dp_props->getValIfPresent(key,res);
|
|
}
|
|
|
|
//! returns whether or not we have a \c property with name \c key
|
|
bool hasProp(const char *key) const {
|
|
if(!dp_props) return false;
|
|
return dp_props->hasVal(key);
|
|
};
|
|
//! \overload
|
|
bool hasProp(const std::string &key) const {
|
|
if(!dp_props) return false;
|
|
return dp_props->hasVal(key);
|
|
};
|
|
|
|
//! clears the value of a \c property
|
|
/*!
|
|
<b>Notes:</b>
|
|
- if no \c property with name \c key exists, a KeyErrorException
|
|
will be thrown.
|
|
- if the \c property is marked as \c computed, it will also be removed
|
|
from our list of \c computedProperties
|
|
*/
|
|
void clearProp(const char *key) const {
|
|
std::string what(key);
|
|
clearProp(what);
|
|
};
|
|
//! \overload
|
|
void clearProp(const std::string &key) const {
|
|
STR_VECT compLst;
|
|
if (getPropIfPresent(detail::computedPropName, compLst)) {
|
|
STR_VECT_I svi = std::find(compLst.begin(), compLst.end(), key);
|
|
if (svi != compLst.end()) {
|
|
compLst.erase(svi);
|
|
dp_props->setVal(detail::computedPropName, compLst);
|
|
}
|
|
}
|
|
dp_props->clearVal(key);
|
|
}
|
|
|
|
//! clears all of our \c computed \c properties
|
|
void clearComputedProps() const {
|
|
STR_VECT compLst;
|
|
if(getPropIfPresent(detail::computedPropName, compLst)) {
|
|
BOOST_FOREACH(const std::string &sv,compLst){
|
|
dp_props->clearVal(sv);
|
|
}
|
|
compLst.clear();
|
|
dp_props->setVal(detail::computedPropName, compLst);
|
|
}
|
|
}
|
|
|
|
//! calculates any of our lazy \c properties
|
|
/*!
|
|
<b>Notes:</b>
|
|
- requires an owning molecule
|
|
*/
|
|
void updatePropertyCache(bool strict=true) { (void)strict; }
|
|
|
|
protected:
|
|
//! sets our owning molecule
|
|
//void setOwningMol(ROMol *other);
|
|
//! sets our owning molecule
|
|
//void setOwningMol(ROMol &other) {setOwningMol(&other);};
|
|
bool df_isAromatic;
|
|
bool df_isConjugated;
|
|
boost::uint8_t d_bondType;
|
|
boost::uint8_t d_dirTag;
|
|
boost::uint8_t d_stereo;
|
|
atomindex_t d_index;
|
|
atomindex_t d_beginAtomIdx,d_endAtomIdx;
|
|
ROMol *dp_mol;
|
|
Dict *dp_props;
|
|
INT_VECT *dp_stereoAtoms;
|
|
|
|
void initBond();
|
|
};
|
|
|
|
};
|
|
|
|
//! allows Bond objects to be dumped to streams
|
|
extern std::ostream & operator<<(std::ostream& target, const RDKit::Bond &b);
|
|
|
|
#endif
|