Coverage Report

Created: 2026-07-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/include/openbabel/ring.h
Line
Count
Source
1
/**********************************************************************
2
ring.h - Deal with rings, find smallest set of smallest rings (SSSR).
3
4
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5
Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6
7
This file is part of the Open Babel project.
8
For more information, see <http://openbabel.org/>
9
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation version 2 of the License.
13
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
***********************************************************************/
19
20
#ifndef OB_RING_H
21
#define OB_RING_H
22
23
#include <deque>
24
#include <algorithm>
25
#include <memory>
26
27
// TODO: Make this work as a free-standing header
28
// Currently only used in ring.cpp which imports mol.h beforehand
29
#include <openbabel/bitvec.h>
30
#include <openbabel/typer.h>
31
32
namespace OpenBabel
33
{
34
35
  class OBMol;
36
  class OBAtom;
37
  class OBBond;
38
  class vector3;
39
40
  // class introduction in ring.cpp
41
  class OBAPI OBRing
42
  {
43
    OBMol *_parent; //!< parent molecule for this ring
44
  public:
45
    //public data members
46
    int ring_id;            //!< a unique id to ensure a stable sort in SSSR determination
47
    std::vector<int> _path; //!< the path of this ring (i.e., the atom indexes)
48
    OBBitVec _pathset;      //!< the path of this ring as a redundant bit vector
49
50
    //! \name Constructors
51
    //@{
52
0
    OBRing()    {}
53
    //! Initialize a ring from a set of atom indexes @p path and with @p size
54
    OBRing(std::vector<int>& path, int size);
55
0
    OBRing(std::vector<int>& path, OBBitVec set) : _path(path), _pathset(set) {}
56
    OBRing(const OBRing &src);
57
    OBRing& operator=(const OBRing &src);
58
    //@}
59
60
    //member functions
61
62
    //! \return the size of this ring (i.e., how many atoms in the cycle)
63
0
    size_t    Size()     const  {    return(_path.size());  }
64
    //! \return the size of this ring (i.e., how many atoms in the cycle)
65
    //! \deprecated Use Size() instead
66
    OB_DEPRECATED_MSG("Use Size() instead")
67
0
    size_t    PathSize() const  {    return(_path.size());  }
68
69
    //! \return whether this ring is aromatic
70
    //! If all atoms in this ring are aromatic, the ring will be considered aromatic
71
    //! \todo This method uses implicit bonding -- bond info is not stored in OBRing
72
    bool   IsAromatic();
73
74
    //! Set the ring type (see OBRingTyper for more)
75
    void SetType(char *type);
76
    //! Set the ring type (see OBRingTyper for more)
77
    void SetType(std::string &type);
78
    //! \return the ring type
79
    char *GetType();
80
    //! \return the index for the root atom. O for furan, S for thiazole, N for pyrrole.
81
    //! For 6 membered aromatic rings, the first non carbon atom is used for root.
82
    //! For 5 members rings the O, S or N (BOSum=3, valence=3) will be used for root
83
    unsigned int GetRootAtom();
84
85
    //! \return Whether atom @p a is a member of this ring
86
    bool   IsMember(OBAtom *a);
87
    //! \return Whether both atoms in bond @p b are in this ring
88
    //! \todo This method uses implicit bonding -- bond info is not stored in OBRing
89
    bool   IsMember(OBBond *b);
90
    //! \return Whether @p i as an atom index is in this ring
91
    bool   IsInRing(int i)
92
0
    {
93
0
      return(_pathset.BitIsSet(i));
94
0
    }
95
96
    //! Set the parent of this ring to @p m
97
0
    void   SetParent(OBMol *m)  {    _parent = m;    }
98
    //! \return the parent of this ring, or NULL if none has been defined
99
0
    OBMol *GetParent()          {    return(_parent);}
100
101
    //! Set the supplied vectors to the @p center of this ring, along with
102
    //! the @p normal (in both directions).
103
    //! \param center The center of the ring
104
    //! \param norm1 The normal of the best-fit plane for this ring
105
    //! \param norm2 -1 * norm1 (i.e., the opposite direction of norm1)
106
    //! \return True (success)
107
    bool findCenterAndNormal(vector3 & center, vector3 &norm1, vector3 &norm2);
108
  private:
109
    char _type[30];   //!< ring type
110
  };
111
112
  //! Comparison function for rings, used by OBRingSearch::SortRings()
113
  //! \return true if a.size() > b.size()
114
  OBAPI bool CompareRingSize(const OBRing *,const OBRing *);
115
116
117
  struct OBRingSearchPrivate; //!< pimpl for OBRingSearch internal state
118
119
  /** \class OBRingSearch ring.h <openbabel/ring.h>
120
      \brief Internal class to facilitate OBMol::FindSSSR()
121
  **/
122
  class OBAPI OBRingSearch
123
  {
124
    OB_DEPRECATED std::vector<OBBond*> _bonds; //!< the internal list of closure bonds (deprecated)
125
    std::vector<OBRing*> _rlist; //!< the internal list of rings
126
    std::unique_ptr<OBRingSearchPrivate> _d; //!< opaque internal state (dedup index, etc.)
127
  public:
128
    OBRingSearch();
129
    ~OBRingSearch();
130
131
    //! Sort ring sizes from smallest to largest
132
    void    SortRings()
133
0
    {
134
0
      std::vector<OBRing*>::iterator j;
135
0
      int ring_id; // for each ring, assign a unique id to ensure a stable sort
136
      
137
0
      for (j = _rlist.begin(), ring_id = 0; j != _rlist.end(); ++j, ++ring_id)
138
0
        (*j)->ring_id = ring_id;
139
0
      std::sort(_rlist.begin(),_rlist.end(),CompareRingSize);
140
0
    }
141
    //! Starting with a full ring set - reduce to SSSR set
142
    void    RemoveRedundant(int);
143
    //! Add a new ring from a "closure" bond: See OBBond::IsClosure()
144
    void    AddRingFromClosure(OBMol &,OBBond *);
145
146
    bool    SaveUniqueRing(std::deque<int>&,std::deque<int>&);
147
148
    //! For debugging only, write the rings to std::cout
149
    void    WriteRings();
150
151
    //! \name Iterator methods -- see OBMolRingIter for iteration over a molecule
152
    //@{
153
    //! \return an iterator pointing to the beginning of the list of rings
154
    std::vector<OBRing*>::iterator BeginRings()
155
0
      {
156
0
        return(_rlist.begin());
157
0
      }
158
    //! \return an iterator pointing to the end of the list of rings
159
    std::vector<OBRing*>::iterator EndRings()
160
0
      {
161
0
        return(_rlist.end());
162
0
      }
163
    //@}
164
  };
165
166
  /** \class OBRTree ring.h <openbabel/ring.h>
167
      \brief Internal class for OBRing search algorithms to create a search tree
168
      of OBAtom objects
169
  **/
170
  class OBAPI OBRTree
171
  {
172
    OBAtom  *_atom; //!< Atom represented by this node in the tree
173
    OBRTree *_prv;  //!< Previous (parent) entry in an OBRing tree
174
  public:
175
    //! Construct a search tree from a possible parent entry and atom entry
176
    OBRTree(OBAtom*,OBRTree*);
177
0
    ~OBRTree()    {}
178
179
    //! \return the OBAtom::GetIdx() index of the atom in this node
180
    int  GetAtomIdx();
181
    //! Recursively find the root of this tree, building up a vector of OBAtom nodes.
182
    void PathToRoot(std::vector<OBAtom*>&);
183
  };
184
185
} // end namespace OpenBabel
186
187
#endif // OB_RING_H
188
189
//! \file ring.h
190
//! \brief Deal with rings, find smallest set of smallest rings (SSSR).