Coverage Report

Created: 2025-10-10 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/include/openbabel/bond.h
Line
Count
Source
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
25.2k
#define OB_AROMATIC_BOND  (1<<1)
42
  //! A solid black wedge in 2D representations -- i.e., "up" from the 2D plane
43
1.84k
#define OB_WEDGE_BOND     (1<<2)
44
  //! A dashed "hash" bond in 2D representations -- i.e., "down" from the 2D plane
45
1.17k
#define OB_HASH_BOND      (1<<3)
46
  //! A bond in a ring
47
11.6k
#define OB_RING_BOND      (1<<4)
48
  //! A bond which "closes" a ring when walking the molecular graph
49
14.7k
#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
18.5k
  if (value) SetFlag(X); \
55
18.5k
  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
       */
73
53.8k
      bool HasFlag(int flag) const { return ((_flags & flag) != 0); }
74
      /**
75
       * Sets the bitwise @p flag
76
       */
77
9.32k
      void SetFlag(int flag) { _flags |= flag; }
78
      /**
79
       * Unsets the bitwise @p flag
80
       */
81
14.3k
      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
      OB_DEPRECATED_MSG("Use OBBitVec objects instead to be fully thread-safe.")
98
      bool Visit;
99
100
      //! Constructor
101
      OBBond();
102
      //! Destructor
103
      virtual ~OBBond();
104
105
      //! \name Bond modification methods
106
      //@{
107
      //! Set the internal bond index
108
      /** \warning This will not update the index in the parent OBMol.
109
          Intended mainly for internal use. Use with care. **/
110
5.03k
      void SetIdx(int idx)        {          _idx = idx;        }
111
5.03k
      void SetId(unsigned long id) { _id = id; }
112
      //! Set the bond order to @p order (i.e., 1 = single, 2 = double, 5 = aromatic)
113
      void SetBondOrder(int order);
114
      //! Set the beginning atom of this bond to @p begin. Does not update @p begin.
115
5.03k
      void SetBegin(OBAtom *begin){          _bgn = begin;      }
116
      //! Set the ending atom of this bond to @p end. Does not update @p end.
117
5.03k
      void SetEnd(OBAtom *end)    {          _end = end;        }
118
      //! Set the parent molecule to @p ptr. Does not update parent.
119
5.03k
      void SetParent(OBMol *ptr)  {        _parent= ptr;        }
120
      //! Change the bond length to @p length, while keeping @p fixed stationary
121
      void SetLength(OBAtom *fixed,double length);
122
      //! Change the bond length to @p length, moving both atoms halfway
123
      //! \since version 2.2
124
      void SetLength(double length);
125
      //! Set the main bond information (i.e., when creating a bond)
126
      void Set(int index, OBAtom* begin,OBAtom* end,int order,int flags);
127
      //! Mark that this bond is aromatic. Does not update atoms or validate.
128
4.81k
      void SetAromatic(bool value=true)    { SET_OR_UNSET_FLAG(OB_AROMATIC_BOND); }
129
      /**
130
       * Mark that this bond has 2D "wedge" notation (i.e., goes in a positive
131
       * Z direction from the beginning to end atoms)
132
       */
133
0
      void SetWedge(bool value=true) { SET_OR_UNSET_FLAG(Wedge); }
134
      /**
135
       * Mark that this bond has 2D "hash" notation (i.e., goes in a negative
136
       * Z direction from the beginning to end atoms)
137
       */
138
0
      void SetHash(bool value=true) { SET_OR_UNSET_FLAG(Hash); }
139
      /**
140
       * Set the WedgeOrHash flag on a bond (??)
141
       */
142
0
      void SetWedgeOrHash(bool value=true) { SET_OR_UNSET_FLAG(WedgeOrHash); }
143
      //! Mark that this bond is in a ring. Primarily for internal use.
144
7.82k
      void SetInRing(bool value=true) { SET_OR_UNSET_FLAG(OB_RING_BOND); }
145
      //! Mark that this bond indicates a ring closure when walking the molecule
146
      /** \warning This is for internal use only. All closure bonds are marked
147
          automatically by lazy evaluation when requesting
148
          OBBond::IsClosure() **/
149
5.94k
      void SetClosure(bool value=true)     { SET_OR_UNSET_FLAG(OB_CLOSURE_BOND); }
150
      //@}
151
152
      //! \name Bond data request methods
153
      //@{
154
      //! \return The unique bond index in a molecule.
155
20.0k
      unsigned int     GetIdx()           const { return(_idx);  }
156
1.98k
      unsigned long GetId()           const { return _id; }
157
      //! \return The bond order for the bond
158
39.7k
      unsigned int     GetBondOrder()     const { return(_order); }
159
      //! \return The set of property flags defined for this bond.
160
4.86k
      unsigned int     GetFlags()         const { return(_flags);      }
161
      //! \return The atom index for the end atom in this bond (from OBAtom::GetIdx()
162
      unsigned int     GetBeginAtomIdx()  const
163
5.89k
        { return (_bgn ? _bgn->GetIdx() : 0); }
164
      //! \return The atom index for the end atom in this bond (from OBAtom::GetIdx()
165
      unsigned int     GetEndAtomIdx()    const
166
3.38k
        { return (_end ? _end->GetIdx() : 0); }
167
      //! \return The "beginning" atom for this bond
168
45.7k
      OBAtom *GetBeginAtom()    { return(_bgn);    }
169
      const OBAtom *GetBeginAtom() const
170
0
        { return(_bgn);    }
171
      //! \return The "end" atom for this bond
172
24.1k
      OBAtom *GetEndAtom()      { return(_end);    }
173
      const OBAtom *GetEndAtom() const
174
0
        { return(_end);    }
175
      //! \return The neighboring atom to @p ptr (i.e., the end if @p ptr is the start)
176
      /** \warning If @p ptr is not part of the bond, the beginning atom
177
          will always be returned **/
178
      OBAtom *GetNbrAtom(OBAtom *ptr)
179
148k
        {
180
148k
          return((ptr != _bgn)? _bgn : _end);
181
148k
        }
182
      //! \return The enclosing OBMol for this bond, or NULL if none is defined.
183
51.9k
      OBMol  *GetParent()                 {return(_parent);}
184
      //! \return The expected "equilibrium" length based on the covalent radii and bond order
185
      /** Length is given in Angstroms **/
186
      double  GetEquibLength() const;
187
      //! \return The current length of this bond in Angstroms
188
      double  GetLength() const;
189
      //! \return The index to the neighboring atom of @p ptr (i.e., the end if @p ptr is the start)
190
      /** \warning If @p ptr is not part of the bond, the beginning atom
191
          index will always be returned **/
192
      unsigned int     GetNbrAtomIdx(OBAtom *ptr)
193
36.1k
        {
194
36.1k
          if (ptr!=_bgn)
195
18.1k
            return (_bgn ? _bgn->GetIdx() : 0);
196
18.0k
          else
197
18.0k
            return (_end ? _end->GetIdx() : 0);
198
36.1k
        }
199
      //! Find the smallest ring containing this bond (returns a NULL pointer if none exists)
200
      OBRing* FindSmallestRing() const;
201
      //@}
202
203
      //! \name property request methods
204
      //@{
205
      //! \return Is the bond aromatic?
206
      //!  (Note that the two atoms of the bond may be aromatic,
207
      //!   but not the bond)
208
      bool IsAromatic() const;
209
      //! \return Is the bond part of a ring?
210
      bool IsInRing() const;
211
      //! \return Is the bond a rotatable bond?
212
      /**  Currently, this function classifies any bond with at least one heavy
213
           atom, no sp-hybrid atoms (e.g., a triple bond somewhere) not in a ring
214
           as a potential rotor if includeRingsBonds is false.  If true, rotors in
215
           rings with more than 3 atoms may be included. No other bond typing is attempted.
216
           For more detailed rotor detection, check the OBRotorList and
217
           OBRotorRules classes **/
218
      bool IsRotor(bool includeRingBonds=false);
219
      /** \return Is the bond an amide link (i.e., between a carbonyl C and a N)?
220
           No distinction is made between primary, secondary, and tertiary amides. **/
221
      bool IsPeriodic() const;
222
      //! \return Is the bond within a periodic unit cell?
223
      bool IsAmide();
224
      /** \return Is the bond a primary amide (i.e., between carbonyl C and a NH2)?
225
           In versions prior to 2.3, this function incorrectly identified secondary amides. **/
226
      bool IsPrimaryAmide();
227
      /** \return Is the bond a secondary amide (i.e., between a carbonyl C and a NH1)?
228
           In versions prior to 2.3, this function incorrectly identified tertiary amides. **/
229
      bool IsSecondaryAmide();
230
      //! \return Is the bond a teriary amide (i.e., between a carbonyl C and a NH0)?
231
      //!  \since version 2.3.
232
      bool IsTertiaryAmide();
233
      //! \return Is the bond an ester link (i.e., between a carbonyl C and an O)?
234
      bool IsEster();
235
      //! \return Is the bond a carbonyl C=O?
236
      bool IsCarbonyl();
237
      //! \return Does this bond "close" a ring when walking the molecular graph?
238
      bool IsClosure();
239
      /** \return Whether this bond is a "wedge" in 2D representations
240
          (i.e., goes in a positive Z direction from the beginning to end atoms) **/
241
677
      bool IsWedge() {    return(HasFlag(OB_WEDGE_BOND));    }
242
      /** \return Whether this bond is a "hash" in 2D representations
243
          (i.e., goes in a negative Z direction from the beginning to end atoms) **/
244
704
      bool IsHash()  {    return(HasFlag(OB_HASH_BOND));     }
245
      /**
246
       * @return True if this bond is either a wedge or hash.
247
       * @note: This is a separate bond type
248
       * @since version 2.3
249
       */
250
828
      bool IsWedgeOrHash() const { return(HasFlag(WedgeOrHash)); }
251
      /**
252
       * @return True if this bond is either a cis or trans.
253
       * @since version 2.3
254
       */
255
0
      bool IsCisOrTrans() const { return(HasFlag(CisOrTrans)); }
256
257
      //! \return whether the geometry around this bond "looks" unsaturated
258
      bool IsDoubleBondGeometry();
259
      //@}
260
261
    }; // class OBBond
262
263
  inline OBAtom* OBAtomAtomIterAdaptor::operator*() const
264
16.0k
  {
265
16.0k
    auto bond = *m_iter;
266
16.0k
    return m_atom != bond->GetBeginAtom() ? bond->GetBeginAtom() : bond->GetEndAtom();
267
16.0k
  }
268
269
  //! A standard iterator over a vector of bonds
270
  typedef std::vector<OBBond*>::iterator OBBondIterator;
271
272
}// namespace OpenBabel
273
274
#endif   // OB_BOND_H
275
276
//! @file bond.h
277
//! @brief Handle bonds