1 /**********************************************************************
2 bond.h - Handle OBBond class.
3 
4 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6 Some portions Copyright (C) 2003 by Michael Banck
7 Some portions Copyright (C) 2008 by Tim Vandermeersch
8 
9 This file is part of the Open Babel project.
10 For more information, see <http://openbabel.org/>
11 
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation version 2 of the License.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20 ***********************************************************************/
21 
22 #ifndef OB_BOND_H
23 #define OB_BOND_H
24 
25 #include <openbabel/babelconfig.h>
26 
27 #ifndef OB_EXTERN
28 #  define OB_EXTERN extern
29 #endif
30 
31 #include <openbabel/base.h>
32 #include <openbabel/atom.h>
33 
34 namespace OpenBabel
35 {
36   class OBAtom;
37   class OBRing;
38 
39   //BOND Property Macros (flags)
40   //! An aromatic bond (regardless of bond order)
41 #define OB_AROMATIC_BOND  (1<<1)
42   //! A solid black wedge in 2D representations -- i.e., "up" from the 2D plane
43 #define OB_WEDGE_BOND     (1<<2)
44   //! A dashed "hash" bond in 2D representations -- i.e., "down" from the 2D plane
45 #define OB_HASH_BOND      (1<<3)
46   //! A bond in a ring
47 #define OB_RING_BOND      (1<<4)
48   //! A bond which "closes" a ring when walking the molecular graph
49 #define OB_CLOSURE_BOND   (1<<10)
50   // 11-16 currently unused
51 #define OB_WEDGE_OR_HASH_BOND     (1<<11)
52 
53 #define SET_OR_UNSET_FLAG(X) \
54   if (value) SetFlag(X); \
55   else     UnsetFlag(X);
56 
57 
58   class OBAPI OBBond: public OBBase
59   {
60     protected:
61       unsigned int                _idx;   //!< Unique edge index used by GetIdx() and SetIdx()
62       OBMol                      *_parent;//!< The molecule which contains me (if any)
63       OBAtom                     *_bgn;   //!< I connect one node
64       OBAtom                     *_end;   //!< to another node
65       char                        _order; //!< Bond order (1, 2, 3, 5=aromatic)
66       unsigned short int          _flags; //!< Any flags for this bond
67       unsigned long                 _id;        //!< unique id
68       //OBBondPrivate * const d;
69 
70       /**
71       * @return True id the @p flag is set.
72        */
HasFlag(int flag)73       bool HasFlag(int flag) const { return ((_flags & flag) != 0); }
74       /**
75        * Sets the bitwise @p flag
76        */
SetFlag(int flag)77       void SetFlag(int flag) { _flags |= flag; }
78       /**
79        * Unsets the bitwise @p flag
80        */
UnsetFlag(int flag)81       void UnsetFlag(int flag) { _flags &= (~(flag)); }
82 
83     public:
84       enum Flag {
85         Aromatic = (1<<1), //!< An aromatic bond (regardless of bond order)
86         Ring     = (1<<4), //!< A bond in a ring
87         Closure  = (1<<10) //!< A bond which "closes" a ring when walking the molecular graph
88       };
89       enum StereoFlag {
90         Wedge       = (1<<2),  //!< A solid black wedge in 2D representations -- i.e., "up" from the 2D plane
91         Hash        = (1<<3),  //!< A dashed "hash" bond in 2D representations -- i.e., "down" from the 2D plane
92         WedgeOrHash = (1<<11), //!< The bond is either wedge or hash, this is a separate flag!
93         CisOrTrans  = (1<<12)  //!< Indicates the 2D/3D coordinates are accidentally cis/trans.
94       };
95       //! Whether this bond has been visited by a graph algorithm
96       /** \deprecated Use OBBitVec objects instead to be fully thread-safe. **/
97       bool Visit;
98 
99       //! Constructor
100       OBBond();
101       //! Destructor
102       virtual ~OBBond();
103 
104       //! \name Bond modification methods
105       //@{
106       //! Set the internal bond index
107       /** \warning This will not update the index in the parent OBMol.
108           Intended mainly for internal use. Use with care. **/
SetIdx(int idx)109       void SetIdx(int idx)        {          _idx = idx;        }
SetId(unsigned long id)110       void SetId(unsigned long id) { _id = id; }
111       //! Set the bond order to @p order (i.e., 1 = single, 2 = double, 5 = aromatic)
112       void SetBondOrder(int order);
113       //! Set the beginning atom of this bond to @p begin. Does not update @p begin.
SetBegin(OBAtom * begin)114       void SetBegin(OBAtom *begin){          _bgn = begin;      }
115       //! Set the ending atom of this bond to @p end. Does not update @p end.
SetEnd(OBAtom * end)116       void SetEnd(OBAtom *end)    {          _end = end;        }
117       //! Set the parent molecule to @p ptr. Does not update parent.
SetParent(OBMol * ptr)118       void SetParent(OBMol *ptr)  {        _parent= ptr;        }
119       //! Change the bond length to @p length, while keeping @p fixed stationary
120       void SetLength(OBAtom *fixed,double length);
121       //! Change the bond length to @p length, moving both atoms halfway
122       //! \since version 2.2
123       void SetLength(double length);
124       //! Set the main bond information (i.e., when creating a bond)
125       void Set(int index, OBAtom* begin,OBAtom* end,int order,int flags);
126       //! Mark that this bond is aromatic. Does not update atoms or validate.
127       void SetAromatic(bool value=true)    { SET_OR_UNSET_FLAG(OB_AROMATIC_BOND); }
128       /**
129        * Mark that this bond has 2D "wedge" notation (i.e., goes in a positive
130        * Z direction from the beginning to end atoms)
131        */
132       void SetWedge(bool value=true) { SET_OR_UNSET_FLAG(Wedge); }
133       /**
134        * Mark that this bond has 2D "hash" notation (i.e., goes in a negative
135        * Z direction from the beginning to end atoms)
136        */
137       void SetHash(bool value=true) { SET_OR_UNSET_FLAG(Hash); }
138       /**
139        * Set the WedgeOrHash flag on a bond (??)
140        */
141       void SetWedgeOrHash(bool value=true) { SET_OR_UNSET_FLAG(WedgeOrHash); }
142       //! Mark that this bond is in a ring. Primarily for internal use.
143       void SetInRing(bool value=true) { SET_OR_UNSET_FLAG(OB_RING_BOND); }
144       //! Mark that this bond indicates a ring closure when walking the molecule
145       /** \warning This is for internal use only. All closure bonds are marked
146           automatically by lazy evaluation when requesting
147           OBBond::IsClosure() **/
148       void SetClosure(bool value=true)     { SET_OR_UNSET_FLAG(OB_CLOSURE_BOND); }
149       //@}
150 
151       //! \name Bond data request methods
152       //@{
153       //! \return The unique bond index in a molecule.
GetIdx()154       unsigned int     GetIdx()           const { return(_idx);  }
GetId()155       unsigned long GetId()           const { return _id; }
156       //! \return The bond order for the bond
GetBondOrder()157       unsigned int     GetBondOrder()     const { return(_order); }
158       //! \return The set of property flags defined for this bond.
GetFlags()159       unsigned int     GetFlags()         const { return(_flags);      }
160       //! \return The atom index for the end atom in this bond (from OBAtom::GetIdx()
GetBeginAtomIdx()161       unsigned int     GetBeginAtomIdx()  const
162         { return (_bgn ? _bgn->GetIdx() : 0); }
163       //! \return The atom index for the end atom in this bond (from OBAtom::GetIdx()
GetEndAtomIdx()164       unsigned int     GetEndAtomIdx()    const
165         { return (_end ? _end->GetIdx() : 0); }
166       //! \return The "beginning" atom for this bond
GetBeginAtom()167       OBAtom *GetBeginAtom()    { return(_bgn);    }
GetBeginAtom()168       const OBAtom *GetBeginAtom() const
169         { return(_bgn);    }
170       //! \return The "end" atom for this bond
GetEndAtom()171       OBAtom *GetEndAtom()      { return(_end);    }
GetEndAtom()172       const OBAtom *GetEndAtom() const
173         { return(_end);    }
174       //! \return The neighboring atom to @p ptr (i.e., the end if @p ptr is the start)
175       /** \warning If @p ptr is not part of the bond, the beginning atom
176           will always be returned **/
GetNbrAtom(OBAtom * ptr)177       OBAtom *GetNbrAtom(OBAtom *ptr)
178         {
179           return((ptr != _bgn)? _bgn : _end);
180         }
181       //! \return The enclosing OBMol for this bond, or NULL if none is defined.
GetParent()182       OBMol  *GetParent()                 {return(_parent);}
183       //! \return The expected "equilibrium" length based on the covalent radii and bond order
184       /** Length is given in Angstroms **/
185       double  GetEquibLength() const;
186       //! \return The current length of this bond in Angstroms
187       double  GetLength() const;
188       //! \return The index to the neighboring atom of @p ptr (i.e., the end if @p ptr is the start)
189       /** \warning If @p ptr is not part of the bond, the beginning atom
190           index will always be returned **/
GetNbrAtomIdx(OBAtom * ptr)191       unsigned int     GetNbrAtomIdx(OBAtom *ptr)
192         {
193           if (ptr!=_bgn)
194             return (_bgn ? _bgn->GetIdx() : 0);
195           else
196             return (_end ? _end->GetIdx() : 0);
197         }
198       //! Find the smallest ring containing this bond (returns a NULL pointer if none exists)
199       OBRing* FindSmallestRing() const;
200       //@}
201 
202       //! \name property request methods
203       //@{
204       //! \return Is the bond aromatic?
205       //!  (Note that the two atoms of the bond may be aromatic,
206       //!   but not the bond)
207       bool IsAromatic() const;
208       //! \return Is the bond part of a ring?
209       bool IsInRing() const;
210       //! \return Is the bond a rotatable bond?
211       /**  Currently, this function classifies any bond with at least one heavy
212            atom, no sp-hybrid atoms (e.g., a triple bond somewhere) not in a ring
213            as a potential rotor if includeRingsBonds is false.  If true, rotors in
214            rings with more than 3 atoms may be included. No other bond typing is attempted.
215            For more detailed rotor detection, check the OBRotorList and
216            OBRotorRules classes **/
217       bool IsRotor(bool includeRingBonds=false);
218       /** \return Is the bond an amide link (i.e., between a carbonyl C and a N)?
219            No distinction is made between primary, secondary, and tertiary amides. **/
220       bool IsPeriodic() const;
221       //! \return Is the bond within a periodic unit cell?
222       bool IsAmide();
223       /** \return Is the bond a primary amide (i.e., between carbonyl C and a NH2)?
224            In versions prior to 2.3, this function incorrectly identified secondary amides. **/
225       bool IsPrimaryAmide();
226       /** \return Is the bond a secondary amide (i.e., between a carbonyl C and a NH1)?
227            In versions prior to 2.3, this function incorrectly identified tertiary amides. **/
228       bool IsSecondaryAmide();
229       //! \return Is the bond a teriary amide (i.e., between a carbonyl C and a NH0)?
230       //!  \since version 2.3.
231       bool IsTertiaryAmide();
232       //! \return Is the bond an ester link (i.e., between a carbonyl C and an O)?
233       bool IsEster();
234       //! \return Is the bond a carbonyl C=O?
235       bool IsCarbonyl();
236       //! \return Does this bond "close" a ring when walking the molecular graph?
237       bool IsClosure();
238       /** \return Whether this bond is a "wedge" in 2D representations
239           (i.e., goes in a positive Z direction from the beginning to end atoms) **/
IsWedge()240       bool IsWedge() {    return(HasFlag(OB_WEDGE_BOND));    }
241       /** \return Whether this bond is a "hash" in 2D representations
242           (i.e., goes in a negative Z direction from the beginning to end atoms) **/
IsHash()243       bool IsHash()  {    return(HasFlag(OB_HASH_BOND));     }
244       /**
245        * @return True if this bond is either a wedge or hash.
246        * @note: This is a separate bond type
247        * @since version 2.3
248        */
IsWedgeOrHash()249       bool IsWedgeOrHash() const { return(HasFlag(WedgeOrHash)); }
250       /**
251        * @return True if this bond is either a cis or trans.
252        * @since version 2.3
253        */
IsCisOrTrans()254       bool IsCisOrTrans() const { return(HasFlag(CisOrTrans)); }
255 
256       //! \return whether the geometry around this bond "looks" unsaturated
257       bool IsDoubleBondGeometry();
258       //@}
259 
260     }; // class OBBond
261 
262   //! A standard iterator over a vector of bonds
263   typedef std::vector<OBBond*>::iterator OBBondIterator;
264 
265 }// namespace OpenBabel
266 
267 #endif   // OB_BOND_H
268 
269 //! @file bond.h
270 //! @brief Handle bonds
271