Coverage Report

Created: 2026-10-28 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.