Coverage Report

Created: 2026-07-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/src/bond.cpp
Line
Count
Source
1
/**********************************************************************
2
bond.cpp - Handle OBBond class
3
4
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5
Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6
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 <openbabel/elements.h>
22
#include <openbabel/oberror.h>
23
#include <openbabel/obutil.h>
24
#include <openbabel/ring.h>
25
#include <openbabel/bond.h>
26
#include <openbabel/mol.h>
27
#include <openbabel/generic.h>
28
#include <climits>
29
30
using namespace std;
31
32
namespace OpenBabel
33
{
34
35
  class OBBondPrivate
36
  {
37
    public:
38
0
      OBBondPrivate() {}
39
  };
40
41
  extern THREAD_LOCAL OBAromaticTyper  aromtyper;
42
  extern OBMessageHandler obErrorLog;
43
44
  /** \class OBBond bond.h <openbabel/bond.h>
45
      \brief Bond class
46
47
      The OBBond class is straightforward in its data access and
48
      modification methods. OBBonds store pointers to the atoms on each end
49
      of the bond. In storing pointers to atoms instead of integer indices,
50
      the necessity of having to reorder bonds when atoms are shuffled,
51
      added, or delete is obviated.
52
53
      While methods indicate "begin" and "end" atoms in the bond, all methods
54
      are designed to be independent of atom ordering, with the exception of
55
      stereochemically aware properties such as IsUp(), IsDown(), IsWedge, or
56
      IsHash().
57
  */
58
59
  // *******************************
60
  // *** OBBond member functions ***
61
  // *******************************
62
63
  OBBond::OBBond() /*: d(new OBBondPrivate)*/
64
84.7M
  {
65
84.7M
    _idx=0;
66
84.7M
    _order=0;
67
84.7M
    _flags=0;
68
84.7M
    _bgn=nullptr;
69
84.7M
    _end=nullptr;
70
84.7M
    _vdata.clear();
71
84.7M
    _parent=nullptr;
72
84.7M
  }
73
74
  OBBond::~OBBond()
75
84.7M
  {
76
    // OBGenericData handled in OBBase parent class.
77
84.7M
  }
78
79
  /** Mark the main information for a bond
80
      \param idx The unique bond index for this bond (inside an OBMol)
81
      \param begin The 'beginning' atom for the bond
82
      \param end The 'end' atom for the bond
83
      \param order The bond order (i.e., 1 = single, 2 = double... 5 = aromatic)
84
      \param flags Any initial property flags
85
   **/
86
  void OBBond::Set(int idx,OBAtom *begin,OBAtom *end,int order,int flags)
87
84.7M
  {
88
84.7M
    SetIdx(idx);
89
84.7M
    SetBegin(begin);
90
84.7M
    SetEnd(end);
91
84.7M
    SetBondOrder(order);
92
84.7M
    SetFlag(flags);
93
84.7M
  }
94
95
  void OBBond::SetBondOrder(int order)
96
92.1M
  {
97
92.1M
    _order = (char)order;
98
92.1M
  }
99
100
  // TODO: Figure out how to consider periodicity, etc.
101
  void OBBond::SetLength(OBAtom *fixed, double length)
102
0
  {
103
0
    unsigned int i;
104
0
    OBMol *mol = (OBMol*)fixed->GetParent();
105
0
    vector3 v1,v2,v3,v4,v5;
106
0
    vector<int> children;
107
108
0
    obErrorLog.ThrowError(__FUNCTION__,
109
0
                          "Ran OpenBabel::SetBondLength", obAuditMsg);
110
111
0
    int a = fixed->GetIdx();
112
0
    int b = GetNbrAtom(fixed)->GetIdx();
113
114
0
    if (a == b)
115
0
      return; // this would be a problem...
116
117
0
    mol->FindChildren(children,a,b);
118
0
    children.push_back(b);
119
120
0
    v1 = GetNbrAtom(fixed)->GetVector();
121
0
    v2 = fixed->GetVector();
122
0
    v3 = v1 - v2;
123
124
0
    if (fabs(v3.length_2()) < 2e-6) { // too small to normalize, move the atoms apart
125
0
      obErrorLog.ThrowError(__FUNCTION__,
126
0
                            "Atoms are both at the same location, moving out of the way.", obWarning);
127
0
      v3.randomUnitVector();
128
0
    } else {
129
0
      v3.normalize();
130
0
    }
131
132
0
    v3 *= length;
133
0
    v3 += v2;
134
0
    v4 = v3 - v1;
135
136
0
    for ( i = 0 ; i < children.size() ; i++ )
137
0
      {
138
0
        v1 = mol->GetAtom(children[i])->GetVector();
139
0
        v1 += v4;
140
0
        mol->GetAtom(children[i])->SetVector(v1);
141
0
      }
142
0
  }
143
144
  void OBBond::SetLength(double length)
145
0
  {
146
0
    OBAtom *atom1 = GetBeginAtom();
147
0
    OBAtom *atom2 = GetEndAtom();
148
149
    //split the length difference in half, and modify the bond twice
150
0
    double firstLength = length + ((GetLength() - length) / 2);
151
152
0
    SetLength(atom1, firstLength);
153
0
    SetLength(atom2, length);
154
0
  }
155
156
  bool OBBond::IsRotor(bool includeRingBonds)
157
716k
  {
158
    // This could be one hellish conditional, but let's break it down
159
    // .. the bond is a single bond
160
716k
    if (_order != 1)
161
82.2k
      return false;
162
163
    // not in a ring, or in a large ring
164
    // and if it's a ring, not sp2
165
634k
    OBRing *ring = FindSmallestRing();
166
634k
    if (ring != nullptr) {
167
185k
      if(!includeRingBonds)
168
185k
        return false;
169
0
      if (ring->Size() <= 3)
170
0
        return false;
171
0
      if (_bgn->GetHyb() == 2 || _end->GetHyb() == 2)
172
0
        return false;
173
0
    }
174
175
    // atoms are not sp hybrids
176
448k
    if (_bgn->GetHyb() == 1 || _end->GetHyb() == 1)
177
340k
      return false;
178
179
    // not just an -OH or -NH2, etc.
180
    // maybe we want to add this as an option
181
    //    rotatable = rotatable && ((_bgn->IsHeteroatom() || _bgn->GetHvyDegree() > 1)
182
    //                               && (_end->IsHeteroatom() || _end->GetHvyDegree() > 1) );
183
107k
    return (_bgn->GetHvyDegree() > 1 && _end->GetHvyDegree() > 1);
184
448k
  }
185
  
186
  bool OBBond::IsPeriodic() const
187
118M
  {
188
118M
    OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
189
118M
    return mol->IsPeriodic();
190
118M
  }
191
192
   bool OBBond::IsAmide()
193
0
   {
194
0
      OBAtom *c,*n;
195
0
      c = n = nullptr;
196
197
      // Look for C-N bond
198
0
      if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
199
0
      {
200
0
         c = (OBAtom*)_bgn;
201
0
         n = (OBAtom*)_end;
202
0
      }
203
0
      if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
204
0
      {
205
0
         c = (OBAtom*)_end;
206
0
         n = (OBAtom*)_bgn;
207
0
      }
208
0
      if (!c || !n) return(false);
209
0
      if (GetBondOrder() != 1) return(false);
210
0
      if (n->GetTotalDegree() != 3) return false; // must be a degree 3 nitrogen
211
212
      // Make sure C is attached to =O
213
0
      OBBond *bond;
214
0
      vector<OBBond*>::iterator i;
215
0
      for (bond = c->BeginBond(i); bond; bond = c->NextBond(i))
216
0
      {
217
0
         if (bond->IsCarbonyl()) return(true);
218
0
      }
219
220
      // Return
221
0
      return(false);
222
0
   }
223
224
   bool OBBond::IsPrimaryAmide()
225
0
   {
226
0
      OBAtom *c,*n;
227
0
      c = n = nullptr;
228
229
      // Look for C-N bond
230
0
      if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
231
0
      {
232
0
         c = (OBAtom*)_bgn;
233
0
         n = (OBAtom*)_end;
234
0
      }
235
0
      if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
236
0
      {
237
0
         c = (OBAtom*)_end;
238
0
         n = (OBAtom*)_bgn;
239
0
      }
240
0
      if (!c || !n) return(false);
241
0
      if (GetBondOrder() != 1) return(false);
242
0
      if (n->GetTotalDegree() != 3) return false; // must be a degree 3 nitrogen
243
244
      // Make sure that N is connected to one non-H
245
0
      if (n->GetHvyDegree() != 1) return(false);
246
247
      // Make sure C is attached to =O
248
0
      OBBond *bond;
249
0
      vector<OBBond*>::iterator i;
250
0
      for (bond = c->BeginBond(i); bond; bond = c->NextBond(i))
251
0
      {
252
0
         if (bond->IsCarbonyl()) return(true);
253
0
      }
254
255
0
      return(false);
256
0
   }
257
258
   bool OBBond::IsSecondaryAmide()
259
0
   {
260
0
      OBAtom *c,*n;
261
0
      c = n = nullptr;
262
263
      // Look for C-N bond
264
0
      if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
265
0
      {
266
0
         c = (OBAtom*)_bgn;
267
0
         n = (OBAtom*)_end;
268
0
      }
269
0
      if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
270
0
      {
271
0
         c = (OBAtom*)_end;
272
0
         n = (OBAtom*)_bgn;
273
0
      }
274
0
      if (!c || !n) return(false);
275
0
      if (GetBondOrder() != 1) return(false);
276
0
      if (n->GetTotalDegree() != 3) return false; // must be a degree 3 nitrogen
277
278
      // Make sure that N is connected to two non-H atoms
279
0
      if (n->GetHvyDegree() != 2) return(false);
280
281
      // Make sure C is attached to =O
282
0
      OBBond *bond;
283
0
      vector<OBBond*>::iterator i;
284
0
      for (bond = c->BeginBond(i); bond; bond = c->NextBond(i))
285
0
      {
286
0
         if (bond->IsCarbonyl()) return(true);
287
0
      }
288
289
0
      return(false);
290
0
   }
291
292
   bool OBBond::IsTertiaryAmide()
293
0
   {
294
0
      OBAtom *c,*n;
295
0
      c = n = nullptr;
296
297
      // Look for C-N bond
298
0
      if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
299
0
      {
300
0
         c = (OBAtom*)_bgn;
301
0
         n = (OBAtom*)_end;
302
0
      }
303
0
      if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
304
0
      {
305
0
         c = (OBAtom*)_end;
306
0
         n = (OBAtom*)_bgn;
307
0
      }
308
0
      if (!c || !n) return(false);
309
0
      if (GetBondOrder() != 1) return(false);
310
0
      if (n->GetTotalDegree() != 3) return false; // must be a degree 3 nitrogen
311
312
      // Make sure that N is connected to three non-H atoms
313
0
      if (n->GetHvyDegree() != 3) return(false);
314
315
      // Make sure C is attached to =O
316
0
      OBBond *bond;
317
0
      vector<OBBond*>::iterator i;
318
0
      for (bond = c->BeginBond(i); bond; bond = c->NextBond(i))
319
0
      {
320
0
         if (bond->IsCarbonyl()) return(true);
321
0
      }
322
323
0
      return(false);
324
0
   }
325
326
/*
327
  bool OBBond::IsAmide()
328
  {
329
    OBAtom *a1,*a2;
330
    a1 = a2 = NULL;
331
332
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
333
      {
334
        a1 = (OBAtom*)_bgn;
335
        a2 = (OBAtom*)_end;
336
      }
337
338
    if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
339
      {
340
        a1 = (OBAtom*)_end;
341
        a2 = (OBAtom*)_bgn;
342
      }
343
344
    if (!a1 || !a2)
345
      return(false);
346
    if (GetBondOrder() != 1)
347
      return(false);
348
349
    OBBond *bond;
350
    vector<OBBond*>::iterator i;
351
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
352
      if (bond->IsCarbonyl())
353
        return(true);
354
355
    return(false);
356
  }
357
358
  bool OBBond::IsPrimaryAmide()
359
  {
360
    OBAtom *a1,*a2;
361
    a1 = a2 = NULL;
362
363
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
364
      {
365
        a1 = (OBAtom*)_bgn;
366
        a2 = (OBAtom*)_end;
367
      }
368
369
    if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
370
      {
371
        a1 = (OBAtom*)_end;
372
        a2 = (OBAtom*)_bgn;
373
      }
374
375
    if (!a1 || !a2)
376
      return(false);
377
    if (GetBondOrder() != 1)
378
      return(false);
379
380
    OBBond *bond;
381
    vector<OBBond*>::iterator i;
382
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
383
      if (bond->IsCarbonyl())
384
        if (a2->GetHvyDegree() == 2)
385
          return(true);
386
387
    return(false);
388
  }
389
390
  bool OBBond::IsSecondaryAmide()
391
  {
392
    OBAtom *a1,*a2;
393
    a1 = a2 = NULL;
394
395
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
396
      {
397
        a1 = (OBAtom*)_bgn;
398
        a2 = (OBAtom*)_end;
399
      }
400
401
    if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
402
      {
403
        a1 = (OBAtom*)_end;
404
        a2 = (OBAtom*)_bgn;
405
      }
406
407
    if (!a1 || !a2)
408
      return(false);
409
    if (GetBondOrder() != 1)
410
      return(false);
411
412
    OBBond *bond;
413
    vector<OBBond*>::iterator i;
414
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
415
      if (bond->IsCarbonyl())
416
        if (a2->GetHvyDegree() == 3)
417
          return(true);
418
419
    return(false);
420
  }
421
*/
422
423
  bool OBBond::IsEster()
424
0
  {
425
0
    OBAtom *a1,*a2;
426
0
    a1 = a2 = nullptr;
427
428
0
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8)
429
0
      {
430
0
        a1 = (OBAtom*)_bgn;
431
0
        a2 = (OBAtom*)_end;
432
0
      }
433
434
0
    if (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6)
435
0
      {
436
0
        a1 = (OBAtom*)_end;
437
0
        a2 = (OBAtom*)_bgn;
438
0
      }
439
440
0
    if (!a1 || !a2)
441
0
      return(false);
442
0
    if (GetBondOrder() != 1)
443
0
      return(false);
444
445
0
    OBBond *bond;
446
0
    vector<OBBond*>::iterator i;
447
0
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
448
0
      if (bond->IsCarbonyl())
449
0
        return(true);
450
451
0
    return(false);
452
0
  }
453
454
  bool OBBond::IsCarbonyl()
455
0
  {
456
0
    if (GetBondOrder() != 2)
457
0
      return(false);
458
459
0
    if ((_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8) ||
460
0
        (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6))
461
0
      return(true);
462
463
0
    return(false);
464
0
  }
465
466
  bool OBBond::IsAromatic() const
467
452M
  {
468
452M
    OBMol *mol = ((OBBond*)this)->GetParent();
469
452M
    if (!mol->HasAromaticPerceived())
470
10.3k
        aromtyper.AssignAromaticFlags(*mol);
471
472
452M
    if (this->HasFlag(OB_AROMATIC_BOND))
473
225M
      return true;
474
475
226M
    return false;
476
452M
  }
477
478
  /*! This method checks if the geometry around this bond looks unsaturated
479
    by measuring the torsion angles formed by all connected atoms X-start=end-Y
480
    and checking that they are close to 0 or 180 degrees */
481
  bool OBBond::IsDoubleBondGeometry()
482
1.17k
  {
483
1.17k
    double torsion;
484
1.17k
    OBAtom *nbrStart,*nbrEnd;
485
1.17k
    vector<OBBond*>::iterator i,j;
486
    // We concentrate on sp2 atoms with valence up to 3 and ignore the rest (like sp1 or S,P)
487
    // As this is called from PerceiveBondOrders, GetHyb() may still be undefined.
488
1.17k
    if (_bgn->GetHyb()==1 || _bgn->GetExplicitDegree()>3||
489
1.17k
        _end->GetHyb()==1 || _end->GetExplicitDegree()>3)
490
0
      return(true);
491
492
2.75k
    for (nbrStart = static_cast<OBAtom*>(_bgn)->BeginNbrAtom(i); nbrStart;
493
1.57k
         nbrStart = static_cast<OBAtom*>(_bgn)->NextNbrAtom(i))
494
1.59k
      {
495
1.59k
        if (nbrStart != _end)
496
436
          {
497
436
            for (nbrEnd = static_cast<OBAtom*>(_end)->BeginNbrAtom(j);
498
1.22k
                 nbrEnd; nbrEnd = static_cast<OBAtom*>(_end)->NextNbrAtom(j))
499
801
              {
500
801
                if (nbrEnd != _bgn)
501
378
                  {
502
378
                    torsion=fabs(_parent->GetTorsion(nbrStart, _bgn, _end, nbrEnd));
503
504
                    // >12&&<168 not enough
505
378
                    if (torsion > 15.0  && torsion < 160.0)
506
16
                      {
507
                        // Geometry does not match a double bond
508
16
                        return(false);
509
16
                      }
510
511
378
                  }
512
801
              }  // end loop for neighbors of end
513
436
          }
514
1.59k
      } // end loop for neighbors of start
515
1.15k
    return(true);
516
1.17k
  }
517
518
  bool OBBond::IsInRing() const
519
54.3M
  {
520
54.3M
    OBMol *mol = ((OBBond*)this)->GetParent();
521
54.3M
    if (!mol->HasRingAtomsAndBondsPerceived())
522
10.7k
      mol->FindRingAtomsAndBonds();
523
524
54.3M
    if (((OBBond*)this)->HasFlag(OB_RING_BOND))
525
35.4M
      return true;
526
527
18.9M
    return false;
528
54.3M
  }
529
530
  // Adapted from OBAtom::IsInRingSize()
531
  OBRing* OBBond::FindSmallestRing() const
532
668k
  {
533
668k
    vector<OBRing*> rlist;
534
668k
    vector<OBRing*>::iterator i;
535
536
668k
    OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
537
538
668k
    rlist = mol->GetSSSR();
539
668k
    OBRing* result = nullptr;
540
668k
    size_t min_size = UINT_MAX;
541
20.5M
    for (i = rlist.begin();i != rlist.end();++i) {
542
19.8M
      if ((*i)->IsMember((OBBond*)this) && (*i)->Size() < min_size) {
543
217k
        min_size = (*i)->Size();
544
217k
        result = *i;
545
217k
      }
546
19.8M
    }
547
668k
    return result;
548
668k
  }
549
550
  bool OBBond::IsClosure()
551
139M
  {
552
139M
    OBMol *mol = (OBMol*)GetParent();
553
139M
    if (!mol)
554
0
      return false;
555
139M
    if (!mol->HasClosureBondsPerceived())
556
0
      mol->FindRingAtomsAndBonds();
557
139M
    return HasFlag(OB_CLOSURE_BOND);
558
139M
  }
559
560
  //! \return a "corrected" bonding radius based on the hybridization.
561
  //! Scales the covalent radius by 0.95 for sp2 and 0.90 for sp hybrids
562
  static double CorrectedBondRad(unsigned int elem, unsigned int hyb)
563
0
  {
564
0
    double rad = OBElements::GetCovalentRad(elem);
565
0
    switch (hyb) {
566
0
    case 2:
567
0
      return rad * 0.95;
568
0
    case 1:
569
0
      return rad * 0.90;
570
0
    default:
571
0
      return rad;
572
0
    }
573
0
  }
574
575
  double OBBond::GetEquibLength() const
576
0
  {
577
0
    const OBAtom *begin, *end;
578
579
0
    begin = GetBeginAtom();
580
0
    end = GetEndAtom();
581
0
    double length = CorrectedBondRad(begin->GetAtomicNum(), begin->GetHyb())
582
0
                  + CorrectedBondRad(end->GetAtomicNum(), end->GetHyb());
583
584
0
    if (IsAromatic())
585
0
      return length * 0.93;
586
    
587
0
    switch (_order) {
588
0
    case 3:
589
0
      return length * 0.87;
590
0
    case 2:
591
0
      return length * 0.91;
592
0
    }
593
0
    return length;
594
0
  }
595
596
  double OBBond::GetLength() const
597
118M
  {
598
118M
    double  d2;
599
118M
    const OBAtom *begin, *end;
600
118M
    begin = GetBeginAtom();
601
118M
    end = GetEndAtom();
602
603
118M
    if (!IsPeriodic())
604
118M
      {
605
118M
        d2 = SQUARE(begin->GetX() - end->GetX());
606
118M
        d2 += SQUARE(begin->GetY() - end->GetY());
607
118M
        d2 += SQUARE(begin->GetZ() - end->GetZ());
608
118M
        return(sqrt(d2));
609
118M
      }
610
0
    else
611
0
      {
612
0
        OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
613
0
        OBUnitCell *box = (OBUnitCell*)mol->GetData(OBGenericDataType::UnitCell);
614
0
        return (box->MinimumImageCartesian(begin->GetVector() - end->GetVector())).length();
615
0
      }
616
118M
  }
617
618
  /*Now in OBBase
619
  // OBGenericData methods
620
  bool OBBond::HasData(string &s)
621
  //returns true if the generic attribute/value pair exists
622
  {
623
  if (_vdata.empty())
624
  return(false);
625
626
  vector<OBGenericData*>::iterator i;
627
628
  for (i = _vdata.begin();i != _vdata.end();++i)
629
  if ((*i)->GetAttribute() == s)
630
  return(true);
631
632
  return(false);
633
  }
634
635
  bool OBBond::HasData(const char *s)
636
  //returns true if the generic attribute/value pair exists
637
  {
638
  if (_vdata.empty())
639
  return(false);
640
641
  vector<OBGenericData*>::iterator i;
642
643
  for (i = _vdata.begin();i != _vdata.end();++i)
644
  if ((*i)->GetAttribute() == s)
645
  return(true);
646
647
  return(false);
648
  }
649
650
  bool OBBond::HasData(unsigned int dt)
651
  //returns true if the generic attribute/value pair exists
652
  {
653
  if (_vdata.empty())
654
  return(false);
655
656
  vector<OBGenericData*>::iterator i;
657
658
  for (i = _vdata.begin();i != _vdata.end();++i)
659
  if ((*i)->GetDataType() == dt)
660
  return(true);
661
662
  return(false);
663
  }
664
665
  OBGenericData *OBBond::GetData(string &s)
666
  //returns the value given an attribute
667
  {
668
  vector<OBGenericData*>::iterator i;
669
670
  for (i = _vdata.begin();i != _vdata.end();++i)
671
  if ((*i)->GetAttribute() == s)
672
  return(*i);
673
674
  return(NULL);
675
  }
676
677
  OBGenericData *OBBond::GetData(const char *s)
678
  //returns the value given an attribute
679
  {
680
  vector<OBGenericData*>::iterator i;
681
682
  for (i = _vdata.begin();i != _vdata.end();++i)
683
  if ((*i)->GetAttribute() == s)
684
  return(*i);
685
686
  return(NULL);
687
  }
688
689
  OBGenericData *OBBond::GetData(unsigned int dt)
690
  {
691
  vector<OBGenericData*>::iterator i;
692
  for (i = _vdata.begin();i != _vdata.end();++i)
693
  if ((*i)->GetDataType() == dt)
694
  return(*i);
695
  return(NULL);
696
  }
697
698
  void OBBond::DeleteData(unsigned int dt)
699
  {
700
  vector<OBGenericData*> vdata;
701
  vector<OBGenericData*>::iterator i;
702
  for (i = _vdata.begin();i != _vdata.end();++i)
703
  if ((*i)->GetDataType() == dt)
704
  delete *i;
705
  else
706
  vdata.push_back(*i);
707
  _vdata = vdata;
708
  }
709
710
  void OBBond::DeleteData(vector<OBGenericData*> &vg)
711
  {
712
  vector<OBGenericData*> vdata;
713
  vector<OBGenericData*>::iterator i,j;
714
715
  bool del;
716
  for (i = _vdata.begin();i != _vdata.end();++i)
717
  {
718
  del = false;
719
  for (j = vg.begin();j != vg.end();++j)
720
  if (*i == *j)
721
  {
722
  del = true;
723
  break;
724
  }
725
  if (del)
726
  delete *i;
727
  else
728
  vdata.push_back(*i);
729
  }
730
  _vdata = vdata;
731
  }
732
733
  void OBBond::DeleteData(OBGenericData *gd)
734
  {
735
  vector<OBGenericData*>::iterator i;
736
  for (i = _vdata.begin();i != _vdata.end();++i)
737
  if (*i == gd)
738
  {
739
  delete *i;
740
  _vdata.erase(i);
741
  }
742
743
  }
744
  */
745
746
} // end namespace OpenBabel
747
748
//! \file bond.cpp
749
//! \brief Handle OBBond class