/src/openbabel/src/obiter.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | obiter.cpp - STL-style iterators for Open Babel |
3 | | |
4 | | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. |
5 | | Some portions Copyright (C) 2001-2006 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 | | #include <openbabel/babelconfig.h> |
20 | | |
21 | | #include <vector> |
22 | | |
23 | | #include <openbabel/mol.h> |
24 | | #include <openbabel/atom.h> |
25 | | #include <openbabel/bond.h> |
26 | | #include <openbabel/generic.h> |
27 | | #include <openbabel/obiter.h> |
28 | | |
29 | | using namespace std; |
30 | | |
31 | | namespace OpenBabel |
32 | | { |
33 | | |
34 | | /** \class OBMolAtomIter obiter.h <openbabel/obiter.h> |
35 | | |
36 | | To facilitate iteration through all atoms in a molecule, without resorting |
37 | | to atom indexes (which <strong>will</strong> change in the future), a |
38 | | variety of iterator methods are provided. |
39 | | |
40 | | This has been made significantly easier by a series of macros in the |
41 | | obiter.h header file: |
42 | | |
43 | | \code |
44 | | \#define FOR_ATOMS_OF_MOL(a,m) for( OBMolAtomIter a(m); a; ++a ) |
45 | | \endcode |
46 | | |
47 | | Here is an example: |
48 | | \code |
49 | | #include <openbabel/obiter.h> |
50 | | #include <openbabel/mol.h> |
51 | | |
52 | | OpenBabel::OBMol mol; |
53 | | double exactMass = 0.0; |
54 | | FOR_ATOMS_OF_MOL(a, mol) |
55 | | { |
56 | | // The variable a behaves like OBAtom* when used with -> and * but |
57 | | // but needs to be explicitly converted when appearing as a parameter |
58 | | // in a function call - use &*a |
59 | | |
60 | | exactMass += a->GetExactMass(); |
61 | | } |
62 | | \endcode |
63 | | **/ |
64 | | |
65 | | OBMolAtomIter::OBMolAtomIter(OBMol *mol) |
66 | 0 | { |
67 | 0 | _parent = mol; |
68 | 0 | _ptr = _parent->BeginAtom(_i); |
69 | 0 | } |
70 | | |
71 | | OBMolAtomIter::OBMolAtomIter(OBMol &mol) |
72 | 0 | { |
73 | 0 | _parent = &mol; |
74 | 0 | _ptr = _parent->BeginAtom(_i); |
75 | 0 | } |
76 | | |
77 | | OBMolAtomIter::OBMolAtomIter(const OBMolAtomIter &ai) |
78 | 0 | { |
79 | 0 | _parent = ai._parent; |
80 | 0 | _ptr = ai._ptr; |
81 | 0 | _i = ai._i; |
82 | 0 | } |
83 | | |
84 | | OBMolAtomIter& OBMolAtomIter::operator=(const OBMolAtomIter &ai) |
85 | 0 | { |
86 | 0 | if (this != &ai) |
87 | 0 | { |
88 | 0 | _parent = ai._parent; |
89 | 0 | _ptr = ai._ptr; |
90 | 0 | _i = ai._i; |
91 | 0 | } |
92 | 0 | return *this; |
93 | 0 | } |
94 | | |
95 | | OBMolAtomIter& OBMolAtomIter::operator++() |
96 | 0 | { |
97 | 0 | _ptr = _parent->NextAtom(_i); |
98 | 0 | return *this; |
99 | 0 | } |
100 | | |
101 | | OBMolAtomIter OBMolAtomIter::operator++(int) |
102 | 0 | { |
103 | 0 | OBMolAtomIter tmp(*this); |
104 | 0 | operator++(); |
105 | 0 | return tmp; |
106 | 0 | } |
107 | | |
108 | | /** \class OBMolAtomDFSIter obiter.h <openbabel/obiter.h> |
109 | | |
110 | | \since version 2.1 |
111 | | |
112 | | To facilitate iteration through all atoms in a molecule, without resorting |
113 | | to atom indexes (which <strong>will</strong> change in the future), a |
114 | | variety of iterator methods are provided. |
115 | | |
116 | | This class provides a depth-first search ordering of atoms. When one |
117 | | connected component is exhausted, the iterator will start at another until |
118 | | all atoms are visited. No guarantee is made as to the ordering of |
119 | | iteration through connected components. |
120 | | |
121 | | The iterator maintains an internal stack and list of visited |
122 | | atoms. As such it may not be appropriate for memory-constrained |
123 | | situations when iterating through large molecules. |
124 | | |
125 | | Use of this iterator has been made significantly easier by a series |
126 | | of macros in the obiter.h header file: |
127 | | |
128 | | \code |
129 | | \#define FOR_DFS_OF_MOL(a,m) for( OBMolAtomDFSIter a(m); a; ++a ) |
130 | | \endcode |
131 | | |
132 | | Here is an example: |
133 | | \code |
134 | | #include <openbabel/obiter.h> |
135 | | #include <openbabel/mol.h> |
136 | | |
137 | | OpenBabel::OBMol mol; |
138 | | FOR_DFS_OF_MOL(a, mol) |
139 | | { |
140 | | // The variable a behaves like OBAtom* when used with -> and * but |
141 | | // but needs to be explicitly converted when appearing as a parameter |
142 | | // in a function call - use &*a |
143 | | |
144 | | } |
145 | | \endcode |
146 | | **/ |
147 | | |
148 | | OBMolAtomDFSIter::OBMolAtomDFSIter(OBMol *mol, int StartIndex): |
149 | 0 | _parent(mol), _ptr(_parent->GetAtom(StartIndex)) |
150 | 0 | { |
151 | 0 | if (!_ptr) return; |
152 | | |
153 | 0 | _notVisited.Resize(_parent->NumAtoms()); |
154 | 0 | _notVisited.SetRangeOn(0, _parent->NumAtoms() - 1); |
155 | | |
156 | 0 | _notVisited.SetBitOff(_ptr->GetIdx() - 1); |
157 | |
|
158 | 0 | vector<OBBond*>::iterator i; |
159 | 0 | OBAtom *a; |
160 | |
|
161 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
162 | 0 | { |
163 | 0 | _stack.push(a); |
164 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
165 | 0 | } |
166 | 0 | } |
167 | | |
168 | | OBMolAtomDFSIter::OBMolAtomDFSIter(OBMol &mol, int StartIndex): |
169 | 0 | _parent(&mol), _ptr(_parent->GetAtom(StartIndex)) |
170 | 0 | { |
171 | 0 | if (!_ptr) return; |
172 | | |
173 | 0 | _notVisited.Resize(_parent->NumAtoms()); |
174 | 0 | _notVisited.SetRangeOn(0, _parent->NumAtoms() - 1); |
175 | | |
176 | 0 | _notVisited.SetBitOff(_ptr->GetIdx() - 1); |
177 | |
|
178 | 0 | vector<OBBond*>::iterator i; |
179 | 0 | OBAtom *a; |
180 | |
|
181 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
182 | 0 | { |
183 | 0 | _stack.push(a); |
184 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | OBMolAtomDFSIter::OBMolAtomDFSIter(const OBMolAtomDFSIter &ai) |
189 | 0 | { |
190 | 0 | _parent = ai._parent; |
191 | 0 | _ptr = ai._ptr; |
192 | 0 | _notVisited = ai._notVisited; |
193 | 0 | _stack = ai._stack; |
194 | 0 | } |
195 | | |
196 | | OBMolAtomDFSIter& OBMolAtomDFSIter::operator=(const OBMolAtomDFSIter &ai) |
197 | 0 | { |
198 | 0 | if (this != &ai) |
199 | 0 | { |
200 | 0 | _parent = ai._parent; |
201 | 0 | _ptr = ai._ptr; |
202 | 0 | _notVisited = ai._notVisited; |
203 | 0 | _stack = ai._stack; |
204 | 0 | } |
205 | 0 | return *this; |
206 | 0 | } |
207 | | |
208 | | OBMolAtomDFSIter& OBMolAtomDFSIter::operator++() |
209 | 0 | { |
210 | 0 | if (!_stack.empty()) |
211 | 0 | { |
212 | 0 | _ptr = _stack.top(); |
213 | 0 | _stack.pop(); |
214 | 0 | } |
215 | 0 | else // are there any disconnected subgraphs? |
216 | 0 | { |
217 | 0 | int next = _notVisited.FirstBit(); |
218 | 0 | if (next != _notVisited.EndBit()) |
219 | 0 | { |
220 | 0 | _ptr = _parent->GetAtom(next + 1); |
221 | 0 | _notVisited.SetBitOff(next); |
222 | 0 | } |
223 | 0 | else |
224 | 0 | _ptr = nullptr; |
225 | 0 | } |
226 | |
|
227 | 0 | if (_ptr) |
228 | 0 | { |
229 | 0 | vector<OBBond*>::iterator i; |
230 | 0 | OBAtom *a; |
231 | |
|
232 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
233 | 0 | if (_notVisited[a->GetIdx() - 1]) |
234 | 0 | { |
235 | 0 | _stack.push(a); |
236 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
237 | 0 | } |
238 | 0 | } |
239 | |
|
240 | 0 | return *this; |
241 | 0 | } |
242 | | |
243 | | OBMolAtomDFSIter OBMolAtomDFSIter::operator++(int) |
244 | 0 | { |
245 | 0 | OBMolAtomDFSIter tmp(*this); |
246 | 0 | operator++(); |
247 | 0 | return tmp; |
248 | 0 | } |
249 | | |
250 | | /** \class OBMolAtomBFSIter obiter.h <openbabel/obiter.h> |
251 | | |
252 | | \since version 2.1 |
253 | | |
254 | | To facilitate iteration through all atoms in a molecule, without resorting |
255 | | to atom indexes (which <strong>will</strong> change in the future), a |
256 | | variety of iterator methods are provided. |
257 | | |
258 | | This class provides a breadth-first search ordering of atoms. When one |
259 | | connected component is exhausted, the iterator will start at another until |
260 | | all atoms are visited. No guarantee is made as to the ordering of |
261 | | iteration through connected components. |
262 | | |
263 | | The iterator maintains an internal queue and list of visited |
264 | | atoms. As such it may not be appropriate for memory-constrained |
265 | | situations when iterating through large molecules. |
266 | | |
267 | | Use of this iterator has been made significantly easier by a series |
268 | | of macros in the obiter.h header file: |
269 | | |
270 | | \code |
271 | | \#define FOR_BFS_OF_MOL(a,m) for( OBMolAtomBFSIter a(m); a; ++a ) |
272 | | \endcode |
273 | | |
274 | | Here is an example: |
275 | | \code |
276 | | #include <openbabel/obiter.h> |
277 | | #include <openbabel/mol.h> |
278 | | |
279 | | OpenBabel::OBMol mol; |
280 | | FOR_BFS_OF_MOL(a, mol) |
281 | | { |
282 | | // The variable a behaves like OBAtom* when used with -> and * but |
283 | | // but needs to be explicitly converted when appearing as a parameter |
284 | | // in a function call - use &*a |
285 | | |
286 | | } |
287 | | \endcode |
288 | | **/ |
289 | | |
290 | | OBMolAtomBFSIter::OBMolAtomBFSIter(OBMol *mol, int StartIndex): |
291 | 0 | _parent(mol), _ptr(_parent->GetAtom(StartIndex)) |
292 | 0 | { |
293 | 0 | if (!_ptr) return; |
294 | | |
295 | 0 | _notVisited.Resize(_parent->NumAtoms()); |
296 | 0 | _notVisited.SetRangeOn(0, _parent->NumAtoms() - 1); |
297 | | |
298 | 0 | _notVisited.SetBitOff(_ptr->GetIdx() - 1); |
299 | | |
300 | | // Set up storage for the depths |
301 | 0 | _depth.resize(_parent->NumAtoms() + 1, 0); |
302 | 0 | _depth[_ptr->GetIdx()] = 1; |
303 | |
|
304 | 0 | vector<OBBond*>::iterator i; |
305 | 0 | OBAtom *a; |
306 | |
|
307 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
308 | 0 | { |
309 | 0 | _queue.push(a); |
310 | 0 | _depth[a->GetIdx()] = 2; |
311 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
312 | 0 | } |
313 | 0 | } |
314 | | |
315 | | OBMolAtomBFSIter::OBMolAtomBFSIter(OBMol &mol, int StartIndex): |
316 | 0 | _parent(&mol), _ptr(_parent->GetAtom(StartIndex)) |
317 | 0 | { |
318 | 0 | if (!_ptr) return; |
319 | | |
320 | 0 | _notVisited.Resize(_parent->NumAtoms()); |
321 | 0 | _notVisited.SetRangeOn(0, _parent->NumAtoms() - 1); |
322 | | |
323 | 0 | _notVisited.SetBitOff(_ptr->GetIdx() - 1); |
324 | | |
325 | | // Set up storage for the depths |
326 | 0 | _depth.resize(_parent->NumAtoms() + 1, 0); |
327 | 0 | _depth[_ptr->GetIdx()] = 1; |
328 | |
|
329 | 0 | vector<OBBond*>::iterator i; |
330 | 0 | OBAtom *a; |
331 | |
|
332 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
333 | 0 | { |
334 | 0 | _queue.push(a); |
335 | 0 | _depth[a->GetIdx()] = 2; |
336 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
337 | 0 | } |
338 | 0 | } |
339 | | |
340 | | OBMolAtomBFSIter::OBMolAtomBFSIter(const OBMolAtomBFSIter &ai) |
341 | 0 | { |
342 | 0 | _parent = ai._parent; |
343 | 0 | _ptr = ai._ptr; |
344 | 0 | _notVisited = ai._notVisited; |
345 | 0 | _queue = ai._queue; |
346 | 0 | _depth = ai._depth; |
347 | 0 | } |
348 | | |
349 | | OBMolAtomBFSIter& OBMolAtomBFSIter::operator=(const OBMolAtomBFSIter &ai) |
350 | 0 | { |
351 | 0 | if (this != &ai) |
352 | 0 | { |
353 | 0 | _parent = ai._parent; |
354 | 0 | _ptr = ai._ptr; |
355 | 0 | _notVisited = ai._notVisited; |
356 | 0 | _queue = ai._queue; |
357 | 0 | _depth = ai._depth; |
358 | 0 | } |
359 | 0 | return *this; |
360 | 0 | } |
361 | | |
362 | | OBMolAtomBFSIter& OBMolAtomBFSIter::operator++() |
363 | 0 | { |
364 | 0 | if (!_queue.empty()) |
365 | 0 | { |
366 | 0 | _ptr = _queue.front(); |
367 | 0 | _queue.pop(); |
368 | 0 | } |
369 | 0 | else // are there any disconnected subgraphs? |
370 | 0 | { |
371 | 0 | int next = _notVisited.FirstBit(); |
372 | 0 | if (next != _notVisited.EndBit()) |
373 | 0 | { |
374 | 0 | _ptr = _parent->GetAtom(next + 1); // Atom index issue |
375 | 0 | if (_ptr != nullptr) |
376 | 0 | _depth[_ptr->GetIdx()] = 1; // new island |
377 | 0 | _notVisited.SetBitOff(next); |
378 | 0 | } |
379 | 0 | else |
380 | 0 | _ptr = nullptr; |
381 | 0 | } |
382 | |
|
383 | 0 | if (_ptr) |
384 | 0 | { |
385 | 0 | vector<OBBond*>::iterator i; |
386 | 0 | OBAtom *a; |
387 | |
|
388 | 0 | for (a = _ptr->BeginNbrAtom(i); a; a = _ptr->NextNbrAtom(i)) |
389 | 0 | if (_notVisited[a->GetIdx() - 1]) |
390 | 0 | { |
391 | 0 | _queue.push(a); |
392 | 0 | _depth[a->GetIdx()] = _depth[_ptr->GetIdx()] + 1; |
393 | 0 | _notVisited.SetBitOff(a->GetIdx() - 1); |
394 | 0 | } |
395 | 0 | } |
396 | |
|
397 | 0 | return *this; |
398 | 0 | } |
399 | | |
400 | | OBMolAtomBFSIter OBMolAtomBFSIter::operator++(int) |
401 | 0 | { |
402 | 0 | OBMolAtomBFSIter tmp(*this); |
403 | 0 | operator++(); |
404 | 0 | return tmp; |
405 | 0 | } |
406 | | |
407 | | int OBMolAtomBFSIter::CurrentDepth() const |
408 | 0 | { |
409 | 0 | if (_ptr == nullptr) |
410 | 0 | return 0; |
411 | | |
412 | 0 | return _depth[_ptr->GetIdx()]; |
413 | 0 | } |
414 | | |
415 | | /** \class OBMolBondBFSIter obiter.h <openbabel/obiter.h> |
416 | | |
417 | | \since version 2.3 |
418 | | |
419 | | To facilitate iteration through all bonds in a molecule, without resorting |
420 | | to bond indexes (which <strong>will</strong> change in the future), a |
421 | | variety of iterator methods are provided. |
422 | | |
423 | | This class provides a breadth-first search ordering of bonds. When one |
424 | | connected component is exhausted, the iterator will start at another until |
425 | | all bonds are visited. No guarantee is made as to the ordering of |
426 | | iteration through connected components. |
427 | | |
428 | | The iterator maintains an internal queue and list of visited |
429 | | atoms. As such it may not be appropriate for memory-constrained |
430 | | situations when iterating through large molecules. |
431 | | |
432 | | Use of this iterator has been made significantly easier by a series |
433 | | of macros in the obiter.h header file: |
434 | | |
435 | | \code |
436 | | \#define FOR_BONDBFS_OF_MOL(a,m) for( OBMolBondBFSIter a(m); a; ++a ) |
437 | | \endcode |
438 | | |
439 | | Here is an example: |
440 | | \code |
441 | | #include <openbabel/obiter.h> |
442 | | #include <openbabel/mol.h> |
443 | | |
444 | | OpenBabel::OBMol mol; |
445 | | FOR_BONDBFS_OF_MOL(b, mol) |
446 | | { |
447 | | // The variable b behaves like OBBond* when used with -> and * but |
448 | | // but needs to be explicitly converted when appearing as a parameter |
449 | | // in a function call - use &*a |
450 | | |
451 | | } |
452 | | \endcode |
453 | | **/ |
454 | | |
455 | | OBMolBondBFSIter::OBMolBondBFSIter(OBMol *mol, int StartIndex): |
456 | 0 | _parent(mol) |
457 | 0 | { |
458 | 0 | unsigned int numbonds = _parent->NumBonds(); |
459 | 0 | if (numbonds == 0) { |
460 | 0 | _ptr = nullptr; // mark as invalid |
461 | 0 | return; |
462 | 0 | } |
463 | 0 | _ptr = _parent->GetBond(StartIndex); |
464 | 0 | if (!_ptr) |
465 | 0 | return; |
466 | | |
467 | 0 | _notVisited.Resize(numbonds); |
468 | 0 | _notVisited.SetRangeOn(0, numbonds - 1); |
469 | | |
470 | 0 | _notVisited.SetBitOff(_ptr->GetIdx()); |
471 | | |
472 | | // Set up storage for the depths |
473 | 0 | _depth.resize(_parent->NumBonds(), 0); |
474 | 0 | _depth[_ptr->GetIdx()] = 1; |
475 | |
|
476 | 0 | for( OBAtomBondIter b(_ptr->GetBeginAtom()); b; ++b ) |
477 | 0 | { // Loop thru all bonds attached to the start of the bond |
478 | 0 | if (_notVisited[b->GetIdx()]) { // Don't revisit the initial bond |
479 | 0 | _queue.push(&(*b)); |
480 | 0 | _depth[b->GetIdx()] = 2; |
481 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
482 | 0 | } |
483 | 0 | } |
484 | 0 | for( OBAtomBondIter b(_ptr->GetEndAtom()); b; ++b ) |
485 | 0 | { // Loop thru all bonds attached to the end of the bond |
486 | 0 | if (_notVisited[b->GetIdx()]) { // Don't revisit the initial bond |
487 | 0 | _queue.push(&(*b)); |
488 | 0 | _depth[b->GetIdx()] = 2; |
489 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
490 | 0 | } |
491 | 0 | } |
492 | 0 | } |
493 | | |
494 | | OBMolBondBFSIter::OBMolBondBFSIter(OBMol &mol, int StartIndex): |
495 | 0 | _parent(&mol) |
496 | 0 | { |
497 | 0 | unsigned int numbonds = _parent->NumBonds(); |
498 | 0 | if (numbonds == 0) { |
499 | 0 | _ptr = nullptr; // mark as invalid |
500 | 0 | return; |
501 | 0 | } |
502 | 0 | _ptr = _parent->GetBond(StartIndex); |
503 | 0 | if (!_ptr) |
504 | 0 | return; |
505 | | |
506 | 0 | _notVisited.Resize(numbonds); |
507 | 0 | _notVisited.SetRangeOn(0, numbonds - 1); |
508 | | |
509 | 0 | _notVisited.SetBitOff(_ptr->GetIdx()); |
510 | | |
511 | | // Set up storage for the depths |
512 | 0 | _depth.resize(numbonds, 0); |
513 | 0 | _depth[_ptr->GetIdx()] = 1; |
514 | |
|
515 | 0 | for( OBAtomBondIter b(_ptr->GetBeginAtom()); b; ++b ) |
516 | 0 | { // Loop thru all bonds attached to the start of the bond |
517 | 0 | if (_notVisited[b->GetIdx()]) { // Don't revisit the initial bond |
518 | 0 | _queue.push(&(*b)); |
519 | 0 | _depth[b->GetIdx()] = 2; |
520 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
521 | 0 | } |
522 | 0 | } |
523 | 0 | for( OBAtomBondIter b(_ptr->GetEndAtom()); b; ++b ) |
524 | 0 | { // Loop thru all bonds attached to the end of the bond |
525 | 0 | if (_notVisited[b->GetIdx()]) { // Don't revisit the initial bond |
526 | 0 | _queue.push(&(*b)); |
527 | 0 | _depth[b->GetIdx()] = 2; |
528 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
529 | 0 | } |
530 | 0 | } |
531 | 0 | } |
532 | | |
533 | | OBMolBondBFSIter::OBMolBondBFSIter(const OBMolBondBFSIter &ai) |
534 | 0 | { |
535 | 0 | _parent = ai._parent; |
536 | 0 | _ptr = ai._ptr; |
537 | 0 | _notVisited = ai._notVisited; |
538 | 0 | _queue = ai._queue; |
539 | 0 | _depth = ai._depth; |
540 | 0 | } |
541 | | |
542 | | OBMolBondBFSIter& OBMolBondBFSIter::operator=(const OBMolBondBFSIter &ai) |
543 | 0 | { |
544 | 0 | if (this != &ai) |
545 | 0 | { |
546 | 0 | _parent = ai._parent; |
547 | 0 | _ptr = ai._ptr; |
548 | 0 | _notVisited = ai._notVisited; |
549 | 0 | _queue = ai._queue; |
550 | 0 | _depth = ai._depth; |
551 | 0 | } |
552 | 0 | return *this; |
553 | 0 | } |
554 | | |
555 | | OBMolBondBFSIter& OBMolBondBFSIter::operator++() |
556 | 0 | { |
557 | 0 | if (!_queue.empty()) |
558 | 0 | { |
559 | 0 | _ptr = _queue.front(); |
560 | 0 | _queue.pop(); |
561 | 0 | } |
562 | 0 | else // are there any disconnected subgraphs? |
563 | 0 | { |
564 | 0 | int next = _notVisited.FirstBit(); |
565 | 0 | if (next != _notVisited.EndBit()) |
566 | 0 | { |
567 | 0 | _ptr = _parent->GetBond(next + 1); // Bond index issue |
568 | 0 | if (_ptr != nullptr) |
569 | 0 | _depth[_ptr->GetIdx()] = 1; // new island |
570 | 0 | _notVisited.SetBitOff(next); |
571 | 0 | } |
572 | 0 | else |
573 | 0 | _ptr = nullptr; |
574 | 0 | } |
575 | |
|
576 | 0 | if (_ptr) { |
577 | 0 | for( OBAtomBondIter b(_ptr->GetBeginAtom()); b; ++b ) |
578 | 0 | { // Loop thru all bonds attached to the start of the bond |
579 | 0 | if (_notVisited[b->GetIdx()]) { |
580 | 0 | _queue.push(&(*b)); |
581 | 0 | _depth[b->GetIdx()] = 2; |
582 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
583 | 0 | } |
584 | 0 | } |
585 | 0 | for( OBAtomBondIter b(_ptr->GetEndAtom()); b; ++b ) |
586 | 0 | { // Loop thru all bonds attached to the end of the bond |
587 | 0 | if (_notVisited[b->GetIdx()]) { |
588 | 0 | _queue.push(&(*b)); |
589 | 0 | _depth[b->GetIdx()] = 2; |
590 | 0 | _notVisited.SetBitOff(b->GetIdx()); |
591 | 0 | } |
592 | 0 | } |
593 | 0 | } |
594 | 0 | return *this; |
595 | 0 | } |
596 | | |
597 | | OBMolBondBFSIter OBMolBondBFSIter::operator++(int) |
598 | 0 | { |
599 | 0 | OBMolBondBFSIter tmp(*this); |
600 | 0 | operator++(); |
601 | 0 | return tmp; |
602 | 0 | } |
603 | | |
604 | | int OBMolBondBFSIter::CurrentDepth() const |
605 | 0 | { |
606 | 0 | if (_ptr == nullptr) |
607 | 0 | return 0; |
608 | | |
609 | 0 | return _depth[_ptr->GetIdx()]; |
610 | 0 | } |
611 | | /////////////////////////////////////////////////////////////////////// |
612 | | |
613 | | /** \class OBMolBondIter obiter.h <openbabel/obiter.h> |
614 | | |
615 | | To facilitate iteration through all bonds in a molecule, without resorting |
616 | | to bond indexes (which may change in the future), a variety of |
617 | | iterators are provided. |
618 | | |
619 | | This has been made significantly easier by a series of macros in the |
620 | | obiter.h header file: |
621 | | |
622 | | \code |
623 | | \#define FOR_BONDS_OF_MOL(b,m) for( OBMolBondIter b(m); b; ++b ) |
624 | | \endcode |
625 | | |
626 | | Here is an example: |
627 | | \code |
628 | | #include <openbabel/obiter.h> |
629 | | #include <openbabel/mol.h> |
630 | | |
631 | | OpenBabel::OBMol mol; |
632 | | unsigned int bondOrderSum = 0; |
633 | | FOR_BONDS_OF_MOL(b, mol) |
634 | | { |
635 | | // The variable b behaves like OBBond* when used with -> and * but |
636 | | // but needs to be explicitly converted when appearing as a parameter |
637 | | // in a function call - use &*b |
638 | | bondOrderSum += b->GetBondOrder(); |
639 | | } |
640 | | \endcode |
641 | | **/ |
642 | | |
643 | | OBMolBondIter::OBMolBondIter(OBMol *mol) |
644 | 0 | { |
645 | 0 | _parent = mol; |
646 | 0 | _ptr = _parent->BeginBond(_i); |
647 | 0 | } |
648 | | |
649 | | OBMolBondIter::OBMolBondIter(OBMol &mol) |
650 | 0 | { |
651 | 0 | _parent = &mol; |
652 | 0 | _ptr = _parent->BeginBond(_i); |
653 | 0 | } |
654 | | |
655 | | OBMolBondIter::OBMolBondIter(const OBMolBondIter &bi) |
656 | 0 | { |
657 | 0 | _parent = bi._parent; |
658 | 0 | _ptr = bi._ptr; |
659 | 0 | _i = bi._i; |
660 | 0 | } |
661 | | |
662 | | OBMolBondIter& OBMolBondIter::operator=(const OBMolBondIter &bi) |
663 | 0 | { |
664 | 0 | if (this != &bi) |
665 | 0 | { |
666 | 0 | _parent = bi._parent; |
667 | 0 | _ptr = bi._ptr; |
668 | 0 | _i = bi._i; |
669 | 0 | } |
670 | 0 | return *this; |
671 | 0 | } |
672 | | |
673 | | OBMolBondIter& OBMolBondIter::operator++() |
674 | 0 | { |
675 | 0 | _ptr = _parent->NextBond(_i); |
676 | 0 | return *this; |
677 | 0 | } |
678 | | |
679 | | OBMolBondIter OBMolBondIter::operator++(int) |
680 | 0 | { |
681 | 0 | OBMolBondIter tmp(*this); |
682 | 0 | operator++(); |
683 | 0 | return tmp; |
684 | 0 | } |
685 | | |
686 | | /** \class OBAtomAtomIter obiter.h <openbabel/obiter.h> |
687 | | |
688 | | To facilitate iteration through all neighbors of an atom, without resorting |
689 | | to bond indexes (which may change in the future), a variety of |
690 | | iterator classes and methods are provided. |
691 | | |
692 | | This has been made significantly easier by a series of macros in the |
693 | | obiter.h header file: |
694 | | |
695 | | \code |
696 | | \#define FOR_NBORS_OF_ATOM(a,p) for( OBAtomAtomIter a(p); a; ++a ) |
697 | | \endcode |
698 | | |
699 | | Here is an example: |
700 | | \code |
701 | | #include <openbabel/obiter.h> |
702 | | #include <openbabel/mol.h> |
703 | | |
704 | | OpenBabel::OBMol mol; |
705 | | FOR_ATOMS_OF_MOL(a, mol) |
706 | | { |
707 | | // The variable a behaves like OBAtom* when used with -> and * but |
708 | | // but needs to be explicitly converted when appearing as a parameter |
709 | | // in a function call - use &*a |
710 | | FOR_NBORS_OF_ATOM(b, &*a) |
711 | | { |
712 | | ... |
713 | | } |
714 | | } |
715 | | \endcode |
716 | | **/ |
717 | | |
718 | | OBAtomAtomIter::OBAtomAtomIter(OBAtom *atm) |
719 | 0 | { |
720 | 0 | _parent = atm; |
721 | 0 | _ptr = _parent->BeginNbrAtom(_i); |
722 | 0 | } |
723 | | |
724 | | OBAtomAtomIter::OBAtomAtomIter(OBAtom &atm) |
725 | 0 | { |
726 | 0 | _parent = &atm; |
727 | 0 | _ptr = _parent->BeginNbrAtom(_i); |
728 | 0 | } |
729 | | |
730 | | OBAtomAtomIter::OBAtomAtomIter(const OBAtomAtomIter &ai) |
731 | 0 | { |
732 | 0 | _parent = ai._parent; |
733 | 0 | _ptr = ai._ptr; |
734 | 0 | _i = ai._i; |
735 | 0 | } |
736 | | |
737 | | OBAtomAtomIter& OBAtomAtomIter::operator=(const OBAtomAtomIter &ai) |
738 | 0 | { |
739 | 0 | if (this != &ai) |
740 | 0 | { |
741 | 0 | _parent = ai._parent; |
742 | 0 | _ptr = ai._ptr; |
743 | 0 | _i = ai._i; |
744 | 0 | } |
745 | 0 | return *this; |
746 | 0 | } |
747 | | |
748 | | OBAtomAtomIter& OBAtomAtomIter::operator++() |
749 | 0 | { |
750 | 0 | _ptr = _parent->NextNbrAtom(_i); |
751 | 0 | return *this; |
752 | 0 | } |
753 | | |
754 | | OBAtomAtomIter OBAtomAtomIter::operator++(int) |
755 | 0 | { |
756 | 0 | OBAtomAtomIter tmp(*this); |
757 | 0 | operator++(); |
758 | 0 | return tmp; |
759 | 0 | } |
760 | | |
761 | | /** \class OBAtomBondIter obiter.h <openbabel/obiter.h> |
762 | | |
763 | | To facilitate iteration through all bonds on an atom, without resorting |
764 | | to bond indexes (which may change in the future) a variety of |
765 | | iterator classes and methods are provided. |
766 | | |
767 | | This has been made significantly easier by a series of macros in the |
768 | | obiter.h header file: |
769 | | |
770 | | \code |
771 | | \#define FOR_BONDS_OF_ATOM(b,p) for( OBAtomBondIter b(p); b; ++b ) |
772 | | \endcode |
773 | | |
774 | | Here is an example: |
775 | | \code |
776 | | #include <openbabel/obiter.h> |
777 | | #include <openbabel/mol.h> |
778 | | |
779 | | OpenBabel::OBAtom atom; |
780 | | unsigned int tripleBondCount; |
781 | | FOR_BONDS_OF_ATOM(b, atom) |
782 | | { |
783 | | // The variable b behaves like OBBond* when used with -> and * but |
784 | | // but needs to be explicitly converted when appearing as a parameter |
785 | | // in a function call - use &*b |
786 | | if (b->GetBondOrder() == 3) |
787 | | tripleBondCount++; |
788 | | } |
789 | | \endcode |
790 | | **/ |
791 | | |
792 | | OBAtomBondIter::OBAtomBondIter(OBAtom *atm) |
793 | 0 | { |
794 | 0 | _parent = atm; |
795 | 0 | _ptr = _parent->BeginBond(_i); |
796 | 0 | } |
797 | | |
798 | | OBAtomBondIter::OBAtomBondIter(OBAtom &atm) |
799 | 0 | { |
800 | 0 | _parent = &atm; |
801 | 0 | _ptr = _parent->BeginBond(_i); |
802 | 0 | } |
803 | | |
804 | | OBAtomBondIter::OBAtomBondIter(const OBAtomBondIter &bi) |
805 | 0 | { |
806 | 0 | _parent = bi._parent; |
807 | 0 | _ptr = bi._ptr; |
808 | 0 | _i = bi._i; |
809 | 0 | } |
810 | | |
811 | | OBAtomBondIter& OBAtomBondIter::operator=(const OBAtomBondIter &bi) |
812 | 0 | { |
813 | 0 | if (this != &bi) |
814 | 0 | { |
815 | 0 | _parent = bi._parent; |
816 | 0 | _ptr = bi._ptr; |
817 | 0 | _i = bi._i; |
818 | 0 | } |
819 | 0 | return *this; |
820 | 0 | } |
821 | | |
822 | | OBAtomBondIter& OBAtomBondIter::operator++() |
823 | 0 | { |
824 | 0 | _ptr = _parent->NextBond(_i); |
825 | 0 | return *this; |
826 | 0 | } |
827 | | |
828 | | OBAtomBondIter OBAtomBondIter::operator++(int) |
829 | 0 | { |
830 | 0 | OBAtomBondIter tmp(*this); |
831 | 0 | operator++(); |
832 | 0 | return tmp; |
833 | 0 | } |
834 | | |
835 | | /** \class OBResidueIter obiter.h <openbabel/obiter.h> |
836 | | |
837 | | To facilitate iteration through all residues in a molecule, without resorting |
838 | | to residue indexes (which may change in the future) a variety of |
839 | | iterator classes and methods are provided. |
840 | | |
841 | | This has been made significantly easier by a series of macros in the |
842 | | obiter.h header file: |
843 | | |
844 | | \code |
845 | | \#define FOR_RESIDUES_OF_MOL(r,m) for( OBResidueIter r(m); r; ++r ) |
846 | | \endcode |
847 | | |
848 | | Here is an example: |
849 | | \code |
850 | | #include <openbabel/obiter.h> |
851 | | #include <openbabel/mol.h> |
852 | | |
853 | | OpenBabel::OBMol mol; |
854 | | FOR_RESIDUES_OF_MOL(r, mol) |
855 | | { |
856 | | // The variable r behaves like OBResidue* when used with -> and * but |
857 | | // but needs to be explicitly converted when appearing as a parameter |
858 | | // in a function call - use &*r |
859 | | |
860 | | if (r->GetName() == resname && r->GetNum() == rnum) |
861 | | { |
862 | | // got a match, let's go to work |
863 | | ... |
864 | | } |
865 | | } |
866 | | \endcode |
867 | | **/ |
868 | | |
869 | | OBResidueIter::OBResidueIter(OBMol *mol) |
870 | 0 | { |
871 | 0 | _parent = mol; |
872 | 0 | _ptr = _parent->BeginResidue(_i); |
873 | 0 | } |
874 | | |
875 | | OBResidueIter::OBResidueIter(OBMol &mol) |
876 | 0 | { |
877 | 0 | _parent = &mol; |
878 | 0 | _ptr = _parent->BeginResidue(_i); |
879 | 0 | } |
880 | | |
881 | | OBResidueIter::OBResidueIter(const OBResidueIter &ri) |
882 | 0 | { |
883 | 0 | _parent = ri._parent; |
884 | 0 | _ptr = ri._ptr; |
885 | 0 | _i = ri._i; |
886 | 0 | } |
887 | | |
888 | | OBResidueIter& OBResidueIter::operator=(const OBResidueIter &ri) |
889 | 0 | { |
890 | 0 | if (this != &ri) |
891 | 0 | { |
892 | 0 | _parent = ri._parent; |
893 | 0 | _ptr = ri._ptr; |
894 | 0 | _i = ri._i; |
895 | 0 | } |
896 | 0 | return *this; |
897 | 0 | } |
898 | | |
899 | | OBResidueIter& OBResidueIter::operator++() |
900 | 0 | { |
901 | 0 | _ptr = _parent->NextResidue(_i); |
902 | 0 | return *this; |
903 | 0 | } |
904 | | |
905 | | OBResidueIter OBResidueIter::operator++(int) |
906 | 0 | { |
907 | 0 | OBResidueIter tmp(*this); |
908 | 0 | operator++(); |
909 | 0 | return tmp; |
910 | 0 | } |
911 | | |
912 | | /** \class OBResidueAtomIter obiter.h <openbabel/obiter.h> |
913 | | |
914 | | To facilitate iteration through all atoms in a residue, without resorting |
915 | | to atom indexes (which may change in the future) a variety of |
916 | | iterator classes and methods are provided. |
917 | | |
918 | | This has been made significantly easier by a series of macros in the |
919 | | obiter.h header file: |
920 | | |
921 | | \code |
922 | | \#define FOR_ATOMS_OF_RESIDUE(a,r) for( OBResidueAtomIter a(r); a; ++a ) |
923 | | \endcode |
924 | | |
925 | | Here is an example: |
926 | | \code |
927 | | #include <openbabel/obiter.h> |
928 | | #include <openbabel/mol.h> |
929 | | |
930 | | OpenBabel::OBMol mol; |
931 | | double residueMass = 0.0; |
932 | | FOR_RESIDUES_OF_MOL(r, mol) |
933 | | { |
934 | | // The variable r behaves like OBResidue* when used with -> and * but |
935 | | // but needs to be explicitly converted when appearing as a parameter |
936 | | // in a function call - use &*r |
937 | | |
938 | | if (r->GetName() == resname && r->GetNum() == rnum) |
939 | | { |
940 | | FOR_ATOMS_OF_RESIDUE(a, &*r) |
941 | | { |
942 | | residueMass += a->GetMass(); |
943 | | } |
944 | | } |
945 | | } |
946 | | \endcode |
947 | | **/ |
948 | | |
949 | | OBResidueAtomIter::OBResidueAtomIter(OBResidue *res): |
950 | 0 | _parent(res), _ptr(_parent->BeginAtom(_i)) |
951 | 0 | { } |
952 | | |
953 | | OBResidueAtomIter::OBResidueAtomIter(OBResidue &res): |
954 | 0 | _parent(&res), _ptr(_parent->BeginAtom(_i)) |
955 | 0 | { } |
956 | | |
957 | | OBResidueAtomIter::OBResidueAtomIter(const OBResidueAtomIter &ri) |
958 | 0 | { |
959 | 0 | _parent = ri._parent; |
960 | 0 | _ptr = ri._ptr; |
961 | 0 | _i = ri._i; |
962 | 0 | } |
963 | | |
964 | | OBResidueAtomIter & OBResidueAtomIter::operator = (const OBResidueAtomIter &ri) |
965 | 0 | { |
966 | 0 | if (this != &ri) |
967 | 0 | { |
968 | 0 | _parent = ri._parent; |
969 | 0 | _ptr = ri._ptr; |
970 | 0 | _i = ri._i; |
971 | 0 | } |
972 | |
|
973 | 0 | return (*this); |
974 | 0 | } |
975 | | |
976 | | OBResidueAtomIter& OBResidueAtomIter::operator++ () |
977 | 0 | { |
978 | 0 | _ptr = _parent->NextAtom(_i); |
979 | 0 | return (*this); |
980 | 0 | } |
981 | | |
982 | | OBResidueAtomIter OBResidueAtomIter::operator++ (int) |
983 | 0 | { |
984 | 0 | OBResidueAtomIter tmp(*this); |
985 | 0 | operator++(); |
986 | 0 | return tmp; |
987 | 0 | } |
988 | | |
989 | | /** \class OBMolRingIter obiter.h <openbabel/obiter.h> |
990 | | |
991 | | \since version 2.1 |
992 | | |
993 | | To facilitate iteration through all rings in a molecule, without resorting |
994 | | to ring indexes (which may change in the future) a variety of |
995 | | iterator classes and methods are provided. One word of warning is that |
996 | | these iterator methods automatically call OBMol::FindSSSR() which may |
997 | | involve a significant performance hit on large molecules. |
998 | | |
999 | | Calling iterator classes has been made significantly easier by a series |
1000 | | of macros in the obiter.h header file: |
1001 | | |
1002 | | \code |
1003 | | \#define FOR_RINGS_OF_MOL(r,m) for( OBMolRingIter r(m); r; ++r ) |
1004 | | \endcode |
1005 | | |
1006 | | Here is an example: |
1007 | | \code |
1008 | | #include <openbabel/obiter.h> |
1009 | | #include <openbabel/mol.h> |
1010 | | |
1011 | | OpenBabel::OBMol mol; |
1012 | | FOR_RINGS_OF_MOL(r, mol) |
1013 | | { |
1014 | | // The variable r behaves like OBRing* when used with -> and * but |
1015 | | // but needs to be explicitly converted when appearing as a parameter |
1016 | | // in a function call - use &*r |
1017 | | |
1018 | | } |
1019 | | \endcode |
1020 | | **/ |
1021 | | |
1022 | 0 | OBMolRingIter::OBMolRingIter(OBMol *mol): _parent(mol), _ptr(nullptr) |
1023 | 0 | { |
1024 | 0 | if (!_parent->HasSSSRPerceived()) |
1025 | 0 | _parent->FindSSSR(); |
1026 | |
|
1027 | 0 | _rings = (OBRingData *) _parent->GetData("SSSR"); |
1028 | 0 | if(_rings) |
1029 | 0 | _ptr = _rings->BeginRing(_i); |
1030 | 0 | } |
1031 | | |
1032 | 0 | OBMolRingIter::OBMolRingIter(OBMol &mol): _parent(&mol), _ptr(nullptr) |
1033 | 0 | { |
1034 | 0 | if (!_parent->HasSSSRPerceived()) |
1035 | 0 | _parent->FindSSSR(); |
1036 | |
|
1037 | 0 | _rings = (OBRingData *) _parent->GetData("SSSR"); |
1038 | 0 | if (_rings) |
1039 | 0 | _ptr = _rings->BeginRing(_i); |
1040 | 0 | } |
1041 | | |
1042 | | OBMolRingIter::OBMolRingIter(const OBMolRingIter &ri) |
1043 | 0 | { |
1044 | 0 | _parent = ri._parent; |
1045 | 0 | _ptr = ri._ptr; |
1046 | 0 | _rings = ri._rings; |
1047 | 0 | _i = ri._i; |
1048 | 0 | } |
1049 | | |
1050 | | OBMolRingIter& OBMolRingIter::operator=(const OBMolRingIter &ri) |
1051 | 0 | { |
1052 | 0 | if (this != &ri) |
1053 | 0 | { |
1054 | 0 | _parent = ri._parent; |
1055 | 0 | _ptr = ri._ptr; |
1056 | 0 | _rings = ri._rings; |
1057 | 0 | _i = ri._i; |
1058 | 0 | } |
1059 | 0 | return *this; |
1060 | 0 | } |
1061 | | |
1062 | | OBMolRingIter& OBMolRingIter::operator++() |
1063 | 0 | { |
1064 | 0 | if (_rings) |
1065 | 0 | _ptr = _rings->NextRing(_i); |
1066 | 0 | return *this; |
1067 | 0 | } |
1068 | | |
1069 | | OBMolRingIter OBMolRingIter::operator++(int) |
1070 | 0 | { |
1071 | 0 | OBMolRingIter tmp(*this); |
1072 | 0 | operator++(); |
1073 | 0 | return tmp; |
1074 | 0 | } |
1075 | | |
1076 | | /** \class OBMolAngleIter obiter.h <openbabel/obiter.h> |
1077 | | |
1078 | | \since version 2.1 |
1079 | | |
1080 | | To facilitate iteration through all angles in a molecule, without resorting |
1081 | | to atom indexes (which <strong>will</strong> change in the future), a |
1082 | | variety of iterator methods are provided. |
1083 | | |
1084 | | This has been made significantly easier by a series of macros in the |
1085 | | obiter.h header file: |
1086 | | |
1087 | | \code |
1088 | | \#define FOR_ANGLES_OF_MOL(a,m) for( OBMolAngleIter a(m); a; a++ ) |
1089 | | \endcode |
1090 | | |
1091 | | Here is an example: |
1092 | | \code |
1093 | | #include <openbabel/obiter.h> |
1094 | | #include <openbabel/mol.h> |
1095 | | |
1096 | | OpenBabel::OBMol mol; |
1097 | | OpenBabel::OBAtom *a, *b, *c; |
1098 | | double ang; |
1099 | | |
1100 | | FOR_ANGLES_OF_MOL(angle, mol) |
1101 | | { |
1102 | | // The variable a behaves like OBAngle* when used with -> and * but |
1103 | | // but needs to be explicitly converted when appearing as a parameter |
1104 | | // in a function call - use &*a |
1105 | | |
1106 | | b = _mol.GetAtom((*angle)[0] + 1); |
1107 | | a = _mol.GetAtom((*angle)[1] + 1); |
1108 | | c = _mol.GetAtom((*angle)[2] + 1); |
1109 | | ang = a->GetAngle(b->GetIdx(), c->GetIdx()); |
1110 | | } |
1111 | | \endcode |
1112 | | **/ |
1113 | | |
1114 | | OBMolAngleIter::OBMolAngleIter(OBMol *mol) |
1115 | 0 | { |
1116 | 0 | mol->FindAngles(); |
1117 | 0 | OBAngleData *ad = (OBAngleData *) mol->GetData(OBGenericDataType::AngleData); |
1118 | 0 | ad->FillAngleArray(_vangle); |
1119 | |
|
1120 | 0 | _parent = mol; |
1121 | 0 | if (!_vangle.empty()) { |
1122 | 0 | _i = _vangle.begin(); |
1123 | 0 | _angle = *_i; |
1124 | 0 | } else { |
1125 | 0 | _i = _vangle.end(); |
1126 | 0 | } |
1127 | 0 | } |
1128 | | |
1129 | | OBMolAngleIter::OBMolAngleIter(OBMol &mol) |
1130 | 0 | { |
1131 | 0 | mol.FindAngles(); |
1132 | 0 | OBAngleData *ad = (OBAngleData *) mol.GetData(OBGenericDataType::AngleData); |
1133 | 0 | ad->FillAngleArray(_vangle); |
1134 | |
|
1135 | 0 | _parent = &mol; |
1136 | 0 | if (!_vangle.empty()) { |
1137 | 0 | _i = _vangle.begin(); |
1138 | 0 | _angle = *_i; |
1139 | 0 | } else { |
1140 | 0 | _i = _vangle.end(); |
1141 | 0 | } |
1142 | 0 | } |
1143 | | |
1144 | | OBMolAngleIter::OBMolAngleIter(const OBMolAngleIter &ai) |
1145 | 0 | { |
1146 | 0 | _parent = ai._parent; |
1147 | 0 | _angle = ai._angle; |
1148 | 0 | _vangle = ai._vangle; |
1149 | 0 | _i = ai._i; |
1150 | 0 | } |
1151 | | |
1152 | | OBMolAngleIter& OBMolAngleIter::operator=(const OBMolAngleIter &ai) |
1153 | 0 | { |
1154 | 0 | if (this != &ai) |
1155 | 0 | { |
1156 | 0 | _parent = ai._parent; |
1157 | 0 | _angle = ai._angle; |
1158 | 0 | _vangle = ai._vangle; |
1159 | 0 | _i = ai._i; |
1160 | 0 | } |
1161 | 0 | return *this; |
1162 | 0 | } |
1163 | | |
1164 | | OBMolAngleIter& OBMolAngleIter::operator++() |
1165 | 0 | { |
1166 | 0 | _i++; |
1167 | |
|
1168 | 0 | if (_i != _vangle.end()) |
1169 | 0 | _angle = *_i; |
1170 | |
|
1171 | 0 | return *this; |
1172 | 0 | } |
1173 | | |
1174 | | /** \class OBMolTorsionIter obiter.h <openbabel/obiter.h> |
1175 | | |
1176 | | \since version 2.1 |
1177 | | |
1178 | | To facilitate iteration through all torsions in a molecule, without resorting |
1179 | | to atom indexes (which <strong>will</strong> change in the future), a |
1180 | | variety of iterator methods are provided. |
1181 | | |
1182 | | This has been made significantly easier by a series of macros in the |
1183 | | obiter.h header file: |
1184 | | |
1185 | | \code |
1186 | | \#define FOR_TORSIONS_OF_MOL(t,m) for( OBMolTorsionIter t(m); t; t++ ) |
1187 | | \endcode |
1188 | | |
1189 | | Here is an example: |
1190 | | \code |
1191 | | #include <openbabel/obiter.h> |
1192 | | #include <openbabel/mol.h> |
1193 | | |
1194 | | OpenBabel::OBMol mol; |
1195 | | OpenBabel::OBAtom *a, *b, *c, *d; |
1196 | | double tor; |
1197 | | |
1198 | | FOR_TORSIONS_OF_MOL(t, mol) |
1199 | | { |
1200 | | // The variable a behaves like OBTorsion* when used with -> and * but |
1201 | | // but needs to be explicitly converted when appearing as a parameter |
1202 | | // in a function call - use &*t |
1203 | | |
1204 | | a = _mol.GetAtom((*t)[0] + 1); // indices in vector start from 0!!! |
1205 | | b = _mol.GetAtom((*t)[1] + 1); |
1206 | | c = _mol.GetAtom((*t)[2] + 1); |
1207 | | d = _mol.GetAtom((*t)[3] + 1); |
1208 | | tor = mol.GetTorsion(a->GetIdx(), b->GetIdx(), c->GetIdx(), d->GetIdx()); |
1209 | | } |
1210 | | \endcode |
1211 | | **/ |
1212 | | |
1213 | | OBMolTorsionIter::OBMolTorsionIter(OBMol *mol) |
1214 | 0 | { |
1215 | 0 | mol->FindTorsions(); |
1216 | 0 | OBTorsionData *td = (OBTorsionData *) mol->GetData(OBGenericDataType::TorsionData); |
1217 | 0 | td->FillTorsionArray(_vtorsion); |
1218 | |
|
1219 | 0 | _parent = mol; |
1220 | 0 | if (!_vtorsion.empty()) { |
1221 | 0 | _i = _vtorsion.begin(); |
1222 | 0 | _torsion = *_i; |
1223 | 0 | } else { |
1224 | 0 | _i = _vtorsion.end(); |
1225 | 0 | } |
1226 | 0 | } |
1227 | | |
1228 | | OBMolTorsionIter::OBMolTorsionIter(OBMol &mol) |
1229 | 0 | { |
1230 | 0 | mol.FindTorsions(); |
1231 | 0 | OBTorsionData *td = (OBTorsionData *) mol.GetData(OBGenericDataType::TorsionData); |
1232 | 0 | td->FillTorsionArray(_vtorsion); |
1233 | |
|
1234 | 0 | _parent = &mol; |
1235 | 0 | if (!_vtorsion.empty()) { |
1236 | 0 | _i = _vtorsion.begin(); |
1237 | 0 | _torsion = *_i; |
1238 | 0 | } else { |
1239 | | // Avogadro bug #1972244 |
1240 | | // always set _i, _i will be compared to _vtorsion.end() in OBMolTorsionIter::bool() |
1241 | 0 | _i = _vtorsion.end(); |
1242 | 0 | } |
1243 | 0 | } |
1244 | | |
1245 | | OBMolTorsionIter::OBMolTorsionIter(const OBMolTorsionIter &ai) |
1246 | 0 | { |
1247 | 0 | _parent = ai._parent; |
1248 | 0 | _torsion = ai._torsion; |
1249 | 0 | _vtorsion = ai._vtorsion; |
1250 | 0 | _i = ai._i; |
1251 | 0 | } |
1252 | | |
1253 | | OBMolTorsionIter& OBMolTorsionIter::operator=(const OBMolTorsionIter &ai) |
1254 | 0 | { |
1255 | 0 | if (this != &ai) |
1256 | 0 | { |
1257 | 0 | _parent = ai._parent; |
1258 | 0 | _torsion = ai._torsion; |
1259 | 0 | _vtorsion = ai._vtorsion; |
1260 | 0 | _i = ai._i; |
1261 | 0 | } |
1262 | 0 | return *this; |
1263 | 0 | } |
1264 | | |
1265 | | OBMolTorsionIter& OBMolTorsionIter::operator++() |
1266 | 0 | { |
1267 | 0 | _i++; |
1268 | |
|
1269 | 0 | if (_i != _vtorsion.end()) |
1270 | 0 | _torsion = *_i; |
1271 | |
|
1272 | 0 | return *this; |
1273 | 0 | } |
1274 | | |
1275 | | /** \class OBMolPairIter obiter.h <openbabel/obiter.h> |
1276 | | |
1277 | | \since version 2.1. |
1278 | | |
1279 | | To facilitate iteration through all pairs of atoms in a molecule, without |
1280 | | resorting to bond indexes (which may change in the future), a variety of |
1281 | | iterators are provided. These pairs of atoms are separated by 4 atoms |
1282 | | or more (i.e., these are non-bonded interactions). |
1283 | | |
1284 | | This has been made significantly easier by a series of macros in the |
1285 | | obiter.h header file: |
1286 | | |
1287 | | \code |
1288 | | \#define FOR_PAIRS_OF_MOL(p,m) for( OBMolPairIter p(m); p; p++ ) |
1289 | | \endcode |
1290 | | |
1291 | | Here is an example: |
1292 | | \code |
1293 | | #include <openbabel/obiter.h> |
1294 | | #include <openbabel/mol.h> |
1295 | | |
1296 | | OpenBabel::OBMol mol; |
1297 | | OpenBabel::OBAtom *a, *b; |
1298 | | double rab; |
1299 | | |
1300 | | FOR_PAIRS_OF_MOL(p, mol) |
1301 | | { |
1302 | | // The variable b behaves like OBBond* when used with -> and * but |
1303 | | // but needs to be explicitly converted when appearing as a parameter |
1304 | | // in a function call - use &*p |
1305 | | |
1306 | | a = mol.GetAtom(p->first); |
1307 | | b = mol.GetAtom(p->second); |
1308 | | rab = a->GetDistance(b); |
1309 | | } |
1310 | | \endcode |
1311 | | **/ |
1312 | | |
1313 | | OBMolPairIter::OBMolPairIter(OBMol *mol) |
1314 | 0 | { |
1315 | 0 | _parent = mol; |
1316 | |
|
1317 | 0 | bool foundPair = false; |
1318 | 0 | OBAtom *a = _parent->BeginAtom(_i); |
1319 | 0 | if (!a) |
1320 | 0 | return; |
1321 | 0 | OBAtom *b = _parent->BeginAtom(_j); |
1322 | 0 | while (!foundPair) { |
1323 | 0 | b = _parent->NextAtom(_j); |
1324 | |
|
1325 | 0 | if (!b) { |
1326 | 0 | a = _parent->NextAtom(_i); |
1327 | 0 | if (!a) |
1328 | 0 | return; |
1329 | 0 | b = _parent->BeginAtom(_j); |
1330 | 0 | } |
1331 | | |
1332 | 0 | if (a->GetIdx() >= b->GetIdx()) continue; |
1333 | 0 | if (a->IsConnected(b)) continue; |
1334 | 0 | if (a->IsOneThree(b)) continue; |
1335 | | |
1336 | 0 | foundPair = true; |
1337 | 0 | } |
1338 | | |
1339 | 0 | _pair.clear(); |
1340 | 0 | _pair.push_back(a->GetIdx()); |
1341 | 0 | _pair.push_back(b->GetIdx()); |
1342 | 0 | } |
1343 | | |
1344 | | OBMolPairIter::OBMolPairIter(OBMol &mol) |
1345 | 0 | { |
1346 | 0 | _parent = &mol; |
1347 | |
|
1348 | 0 | bool foundPair = false; |
1349 | 0 | OBAtom *a = _parent->BeginAtom(_i); |
1350 | 0 | if (!a) |
1351 | 0 | return; |
1352 | 0 | OBAtom *b = _parent->BeginAtom(_j); |
1353 | 0 | while (!foundPair) { |
1354 | 0 | b = _parent->NextAtom(_j); |
1355 | |
|
1356 | 0 | if (!b) { |
1357 | 0 | a = _parent->NextAtom(_i); |
1358 | 0 | if (!a) |
1359 | 0 | return; |
1360 | 0 | b = _parent->BeginAtom(_j); |
1361 | 0 | } |
1362 | | |
1363 | 0 | if (a->GetIdx() >= b->GetIdx()) continue; |
1364 | 0 | if (a->IsConnected(b)) continue; |
1365 | 0 | if (a->IsOneThree(b)) continue; |
1366 | | |
1367 | 0 | foundPair = true; |
1368 | 0 | } |
1369 | | |
1370 | 0 | _pair.clear(); |
1371 | 0 | _pair.push_back(a->GetIdx()); |
1372 | 0 | _pair.push_back(b->GetIdx()); |
1373 | 0 | } |
1374 | | |
1375 | | OBMolPairIter::OBMolPairIter(const OBMolPairIter &ai) |
1376 | 0 | { |
1377 | 0 | _parent = ai._parent; |
1378 | 0 | _pair = ai._pair; |
1379 | 0 | _i = ai._i; |
1380 | 0 | _j = ai._j; |
1381 | 0 | } |
1382 | | |
1383 | | OBMolPairIter& OBMolPairIter::operator=(const OBMolPairIter &ai) |
1384 | 0 | { |
1385 | 0 | if (this != &ai) { |
1386 | 0 | _parent = ai._parent; |
1387 | 0 | _pair = ai._pair; |
1388 | 0 | _i = ai._i; |
1389 | 0 | _j = ai._j; |
1390 | 0 | } |
1391 | 0 | return *this; |
1392 | 0 | } |
1393 | | |
1394 | | OBMolPairIter& OBMolPairIter::operator++() |
1395 | 0 | { |
1396 | 0 | _pair.clear(); |
1397 | |
|
1398 | 0 | bool foundPair = false; |
1399 | 0 | OBAtom *a, *b; |
1400 | 0 | a = *_i; |
1401 | 0 | while (!foundPair) { |
1402 | 0 | b = _parent->NextAtom(_j); |
1403 | |
|
1404 | 0 | if (!b) { |
1405 | 0 | a = _parent->NextAtom(_i); |
1406 | 0 | if (!a) |
1407 | 0 | return *this; |
1408 | 0 | b = _parent->BeginAtom(_j); |
1409 | 0 | } |
1410 | | |
1411 | 0 | if (a->GetIdx() >= b->GetIdx()) continue; |
1412 | 0 | if (a->IsConnected(b)) continue; |
1413 | 0 | if (a->IsOneThree(b)) continue; |
1414 | | |
1415 | | |
1416 | 0 | foundPair = true; |
1417 | 0 | } |
1418 | | |
1419 | 0 | _pair.push_back(a->GetIdx()); |
1420 | 0 | _pair.push_back(b->GetIdx()); |
1421 | |
|
1422 | 0 | return *this; |
1423 | 0 | } |
1424 | | |
1425 | | } // namespace OpenBabel |
1426 | | |
1427 | | //! \file obiter.cpp |
1428 | | //! \brief STL-style iterators for Open Babel. |