Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
RingExtractor.hpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #ifndef RingExtractor_INCLUDE_ONCE
33 #define RingExtractor_INCLUDE_ONCE
34 
35 #include <vlCore/glsl_math.hpp>
36 #include <vector>
37 #include <algorithm>
38 #include <map>
39 #include <set>
40 
41 namespace vl
42 {
45  {
46  public:
48 
49  void setMolecule(Molecule* mol) { mMolecule = mol; }
50 
51  Molecule* molecule() const { return mMolecule; }
52 
53  void run()
54  {
55  if (!molecule()->atoms().empty())
56  {
57  bootstrap();
58  removeDoubles();
59  sortCycles();
62  /*keepPlanarCycles(0.10f);*/
63  }
64  }
65 
66  void bootstrap()
67  {
68  if (!molecule()->atoms().empty())
69  {
71  for(int i=0; i<molecule()->atomCount(); ++i)
72  molecule()->atom(i)->setVisited(false);
73  std::vector< ref<Atom> > current_path;
74  depthFirstVisit( molecule()->atoms()[0].get(), current_path );
75  }
76  }
77 
78  void depthFirstVisit(Atom* atom, std::vector< ref<Atom> >& current_path)
79  {
80  if ( !atom->visited() || current_path.empty())
81  {
82  atom->setVisited(true);
83  current_path.push_back(atom);
84  for(unsigned i=0; i<atom->adjacentAtoms().size(); ++i)
85  depthFirstVisit( atom->adjacentAtoms()[i], current_path );
86  current_path.pop_back();
87  atom->setVisited(false);
88  }
89  else // cycle found
90  {
91  /* condition: atom->visited() && !current_path.empty() */
92 
93  for(size_t i = current_path.size()-1; i--; )
94  {
95  if ( current_path[i] == atom )
96  {
97  std::vector< ref<Atom> > cycle;
98  for(; i<current_path.size(); ++i)
99  cycle.push_back( current_path[i] );
100  if (cycle.size() > 2)
101  molecule()->cycles().push_back(cycle);
102  break;
103  }
104  }
105  }
106  }
107 
109  {
110  std::vector< std::vector< ref<Atom> > > kept_cycles;
111  for(unsigned icycle=0; icycle<molecule()->cycles().size(); ++icycle)
112  {
113  int ok = true;
114  for(unsigned iatom=0; iatom<molecule()->cycle(icycle).size(); ++iatom)
115  {
116  int iatom2 = (iatom+1) % molecule()->cycle(icycle).size();
117  Atom* atom1 = molecule()->cycle(icycle)[iatom].get();
118  Atom* atom2 = molecule()->cycle(icycle)[iatom2].get();
119 
120  Bond* bond = molecule()->bond(atom1, atom2);
121  if (bond && bond->bondType() != BT_Aromatic)
122  {
123  ok = false;
124  break;
125  }
126  }
127  if (ok && molecule()->cycle(icycle).size())
128  kept_cycles.push_back(molecule()->cycle(icycle));
129  }
130  molecule()->cycles() = kept_cycles;
131  }
132 
133  void sortCycles()
134  {
135  for(unsigned icycle=0; icycle<molecule()->cycles().size(); ++icycle)
136  {
137  std::vector< ref<Atom> >& cycle = molecule()->cycle(icycle);
138  for(unsigned iatom=0; iatom<cycle.size()-1; ++iatom)
139  {
140  Atom* atom = cycle[iatom].get();
141  for(unsigned j=iatom+1; j<cycle.size(); ++j)
142  {
143  if (atom->isAtomAdjacent(cycle[j].get()))
144  {
145  Atom* tmp = cycle[iatom+1].get();
146  cycle[iatom+1] = cycle[j];
147  cycle[j] = tmp;
148  break;
149  }
150  }
151  }
152  }
153  }
154 
155  void keepPlanarCycles(float epsilon)
156  {
157  std::vector< std::vector< ref<Atom> > > kept_cycles;
158  for(unsigned icycle=0; icycle<molecule()->cycles().size(); ++icycle)
159  {
160  AABB aabb;
161  for(unsigned iatom=0; iatom<molecule()->cycle(icycle).size(); ++iatom)
162  aabb += (vec3)molecule()->cycle(icycle)[iatom]->coordinates();
163  fvec3 center = (fvec3)aabb.center();
164 
165  fvec3 normal;
166  for(unsigned iatom=0; iatom<molecule()->cycle(icycle).size(); ++iatom)
167  {
168  int iatom2 = (iatom+1) % molecule()->cycle(icycle).size();
169  Atom* atom1 = molecule()->cycle(icycle)[iatom].get();
170  Atom* atom2 = molecule()->cycle(icycle)[iatom2].get();
171  fvec3 v1 = (atom1->coordinates()-center).normalize();
172  fvec3 v2 = (atom2->coordinates()-center).normalize();
173  normal += cross(v1, v2);
174  }
175  normal.normalize();
176 
177  int ok = true;
178  for(unsigned iatom=0; iatom<molecule()->cycle(icycle).size(); ++iatom)
179  {
180  fvec3 v1 = molecule()->cycle(icycle)[iatom]->coordinates() - center;
181  float dist = dot(normal, v1);
182  if (fabs(dist)>epsilon)
183  {
184  ok = false;
185  break;
186  }
187  }
188  if (ok && molecule()->cycle(icycle).size())
189  kept_cycles.push_back(molecule()->cycle(icycle));
190  }
191  molecule()->cycles() = kept_cycles;
192  }
193 
195  {
196  for(unsigned icycle=0; icycle<molecule()->cycles().size(); ++icycle)
197  std::stable_sort(molecule()->cycle(icycle).begin(), molecule()->cycle(icycle).end());
198  std::stable_sort(molecule()->cycles().begin(), molecule()->cycles().end());
199  std::vector< std::vector< ref<Atom> > >::iterator new_end = std::unique(molecule()->cycles().begin(), molecule()->cycles().end());
200  std::vector< std::vector< ref<Atom> > > unique_cycles;
201  for(std::vector< std::vector< ref<Atom> > >::iterator it = molecule()->cycles().begin(); it != new_end; ++it)
202  unique_cycles.push_back(*it);
203  molecule()->cycles() = unique_cycles;
204  }
205 
207  {
208  std::vector< std::vector< ref<Atom> > > sub_cycles;
209 
210  std::map<Atom*, bool> my_atom;
211  for(unsigned j=0; j<molecule()->atoms().size(); ++j)
212  my_atom[molecule()->atoms()[j].get()] = false;
213 
214  for(unsigned icycle=0; icycle<molecule()->cycles().size(); ++icycle)
215  {
216  // init
217  for(unsigned j=0; j<molecule()->cycles()[icycle].size(); ++j)
218  my_atom[ molecule()->cycles()[icycle][j].get() ] = true;
219 
220  bool is_sup_cycle = false;
221  for(unsigned j=0; j<molecule()->cycles().size(); ++j)
222  {
223  if (j == icycle)
224  continue;
225  unsigned shared_atoms = 0;
226  for(unsigned k=0; k<molecule()->cycles()[j].size(); k++)
227  shared_atoms += my_atom[ molecule()->cycles()[j][k].get() ] ? 1 : 0;
228  if ( shared_atoms == molecule()->cycles()[j].size() )
229  {
230  is_sup_cycle = true;
231  break;
232  }
233  }
234  if (!is_sup_cycle)
235  sub_cycles.push_back( molecule()->cycles()[icycle] );
236 
237  // reset
238  for(unsigned j=0; j<molecule()->cycles()[icycle].size(); ++j)
239  my_atom[ molecule()->cycles()[icycle][j].get() ] = false;
240  }
241  molecule()->cycles() = sub_cycles;
242  }
243 
244  protected:
246  };
247 }
248 
249 #endif
The Molecule class is used to manage and render 3D molecular structures.
Definition: Molecule.hpp:64
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
bool visited() const
Definition: Atom.hpp:113
const std::vector< ref< Atom > > & cycle(int i) const
Returns the i-th cycle.
Definition: Molecule.hpp:116
const Atom * atom(int index) const
Definition: Molecule.cpp:115
vec3 center() const
Returns the center of the AABB.
Definition: AABB.cpp:184
const std::vector< std::vector< ref< Atom > > > & cycles() const
Returns the list of cycles.
Definition: Molecule.hpp:121
const std::vector< ref< Atom > > & atoms() const
Definition: Molecule.hpp:85
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:277
bool isAtomAdjacent(Atom *atom) const
Definition: Atom.hpp:89
void depthFirstVisit(Atom *atom, std::vector< ref< Atom > > &current_path)
RingExtractor(Molecule *mol)
const fvec3 & coordinates() const
Definition: Atom.hpp:106
Molecule * molecule() const
Visualization Library main namespace.
float dot(float a, float b)
Definition: glsl_math.hpp:1111
void setVisited(bool visited)
Definition: Atom.hpp:112
EBondType bondType() const
Definition: Bond.hpp:77
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
Implements the OpenGL Shading Language convenience functions for scalar and vector operations...
const std::vector< Atom *> & adjacentAtoms() const
Definition: Atom.hpp:97
const Bond * bond(int index) const
Definition: Molecule.cpp:167
The RingExtractor class traverses a molecule&#39;s graph and detects various types of cycles...
int atomCount() const
Definition: Molecule.hpp:88
void keepPlanarCycles(float epsilon)
void computeAtomAdjacency()
Definition: Molecule.cpp:224
The Bond class represents a bond to be used with the Molecule class.
Definition: Bond.hpp:62
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
The Atom class represents an atom to be used with the Molecule class.
Definition: Atom.hpp:51
T normalize(T)
Definition: glsl_math.hpp:1128
void setMolecule(Molecule *mol)