~ubuntu-branches/ubuntu/feisty/openbabel/feisty

« back to all changes in this revision

Viewing changes to src/bond.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-05-14 19:46:01 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060514194601-h3j1wovvc42cigxl
Tags: 2.0.1-1
* New upstream release. (Closes: #341628)
* debian/patches/04_zipstream_fix.diff: Removed, applied upstream.
* debian/rules (DEB_MAKE_CHECK_TARGET): Readded.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**********************************************************************
2
2
bond.cpp - Handle OBBond class
3
 
 
 
3
 
4
4
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5
 
Some portions Copyright (c) 2001-2003 by Geoffrey R. Hutchison
6
 
 
 
5
Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
 
6
 
7
7
This file is part of the Open Babel project.
8
8
For more information, see <http://openbabel.sourceforge.net/>
9
 
 
 
9
 
10
10
This program is free software; you can redistribute it and/or modify
11
11
it under the terms of the GNU General Public License as published by
12
12
the Free Software Foundation version 2 of the License.
13
 
 
 
13
 
14
14
This program is distributed in the hope that it will be useful,
15
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
22
 
23
23
using namespace std;
24
24
 
25
 
namespace OpenBabel {
 
25
namespace OpenBabel
 
26
{
26
27
 
27
28
extern OBAromaticTyper  aromtyper;
28
29
 
41
42
// *******************************
42
43
 
43
44
OBBond::OBBond()
44
 
 {
45
 
   _idx=0;
46
 
   _order=0;
47
 
   _flags=0;
48
 
   _bgn=NULL;
49
 
   _end=NULL;
50
 
   _vdata.clear();
51
 
 }
 
45
{
 
46
    _idx=0;
 
47
    _order=0;
 
48
    _flags=0;
 
49
    _bgn=NULL;
 
50
    _end=NULL;
 
51
    _vdata.clear();
 
52
}
52
53
 
53
54
OBBond::~OBBond()
54
55
{
55
 
  if (!_vdata.empty())
 
56
    if (!_vdata.empty())
56
57
    {
57
 
      vector<OBGenericData*>::iterator m;
58
 
      for (m = _vdata.begin();m != _vdata.end();m++) delete *m;
59
 
      _vdata.clear();
 
58
        vector<OBGenericData*>::iterator m;
 
59
        for (m = _vdata.begin();m != _vdata.end();m++)
 
60
            delete *m;
 
61
        _vdata.clear();
60
62
    }
61
63
}
62
64
 
63
65
void OBBond::Set(int idx,OBAtom *begin,OBAtom *end,int order,int flags)
64
66
{
65
 
  SetIdx(idx);
66
 
  SetBegin(begin);
67
 
  SetEnd(end);
68
 
  SetBO(order);
69
 
  SetFlag(flags);
 
67
    SetIdx(idx);
 
68
    SetBegin(begin);
 
69
    SetEnd(end);
 
70
    SetBO(order);
 
71
    SetFlag(flags);
70
72
}
71
73
 
72
74
void OBBond::SetBO(int order)
73
75
{
74
 
  _order = (char)order;
75
 
  if (order == 5)
 
76
    _order = (char)order;
 
77
    if (order == 5)
76
78
    {
77
 
      SetAromatic();
78
 
      if (_bgn) _bgn->SetAromatic();
79
 
      if (_end) _end->SetAromatic();
 
79
        SetAromatic();
 
80
        if (_bgn)
 
81
            _bgn->SetAromatic();
 
82
        if (_end)
 
83
            _end->SetAromatic();
80
84
    }
81
 
  else            UnsetAromatic();
 
85
    else
 
86
      {
 
87
        if (order == 1)
 
88
          SetKSingle();
 
89
        else if (order == 2)
 
90
          SetKDouble();
 
91
        else if (order == 3)
 
92
          SetKTriple();
 
93
 
 
94
        UnsetAromatic();
 
95
      }
82
96
}
83
97
 
84
98
void OBBond::SetLength(OBAtom *fixed, double length)
85
99
{
86
 
  unsigned int i;
87
 
  OBMol *mol = (OBMol*)fixed->GetParent();
88
 
  vector3 v1,v2,v3,v4,v5;
89
 
  vector<int> children;
90
 
 
91
 
  int a = fixed->GetIdx();
92
 
  int b = GetNbrAtom(fixed)->GetIdx();
93
 
 
94
 
  mol->FindChildren(children,a,b);
95
 
  children.push_back(b);
96
 
 
97
 
  v1 = GetNbrAtom(fixed)->GetVector();
98
 
  v2 = fixed->GetVector();
99
 
  v3 = v1 - v2;
100
 
  v3.normalize();
101
 
  v3 *= length;
102
 
  v3 += v2;
103
 
  v4 = v3 - v1;
104
 
 
105
 
  for ( i = 0 ; i < children.size() ; i++ )
 
100
    unsigned int i;
 
101
    OBMol *mol = (OBMol*)fixed->GetParent();
 
102
    vector3 v1,v2,v3,v4,v5;
 
103
    vector<int> children;
 
104
 
 
105
    obErrorLog.ThrowError(__FUNCTION__,
 
106
                          "Ran OpenBabel::SetBondLength", obAuditMsg);
 
107
 
 
108
    int a = fixed->GetIdx();
 
109
    int b = GetNbrAtom(fixed)->GetIdx();
 
110
 
 
111
    mol->FindChildren(children,a,b);
 
112
    children.push_back(b);
 
113
 
 
114
    v1 = GetNbrAtom(fixed)->GetVector();
 
115
    v2 = fixed->GetVector();
 
116
    v3 = v1 - v2;
 
117
    v3.normalize();
 
118
    v3 *= length;
 
119
    v3 += v2;
 
120
    v4 = v3 - v1;
 
121
 
 
122
    for ( i = 0 ; i < children.size() ; i++ )
106
123
    {
107
 
      v1 = mol->GetAtom(children[i])->GetVector();
108
 
      v1 += v4;
109
 
      mol->GetAtom(children[i])->SetVector(v1);
110
 
      /*
111
 
      idx = (children[i]-1) * 3;
112
 
      c[idx]   += x; 
113
 
      c[idx+1] += y;
114
 
      c[idx+2] += z;
115
 
      */
 
124
        v1 = mol->GetAtom(children[i])->GetVector();
 
125
        v1 += v4;
 
126
        mol->GetAtom(children[i])->SetVector(v1);
 
127
        /*
 
128
        idx = (children[i]-1) * 3;
 
129
        c[idx]   += x; 
 
130
        c[idx+1] += y;
 
131
        c[idx+2] += z;
 
132
        */
116
133
    }
117
134
}
118
 
   
 
135
 
119
136
bool OBBond::IsRotor()
120
137
{
121
 
  return(_bgn->GetHvyValence() > 1 && _end->GetHvyValence() > 1 && 
122
 
         _order == 1 && !IsInRing() && _bgn->GetHyb() != 1 &&
123
 
         _end->GetHyb() != 1);
 
138
    return(_bgn->GetHvyValence() > 1 && _end->GetHvyValence() > 1 &&
 
139
           _order == 1 && !IsInRing() && _bgn->GetHyb() != 1 &&
 
140
           _end->GetHyb() != 1);
124
141
}
125
142
 
126
143
bool OBBond::IsAmide()
127
144
{
128
 
  OBAtom *a1,*a2;
129
 
  a1 = a2 = NULL;
130
 
 
131
 
  if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
132
 
    {a1 = (OBAtom*)_bgn; a2 = (OBAtom*)_end;}
133
 
 
134
 
  if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
135
 
    {a1 = (OBAtom*)_end; a2 = (OBAtom*)_bgn;}
136
 
 
137
 
  if (!a1 || !a2) return(false);
138
 
  if (GetBO() != 1) return(false);
139
 
  
140
 
  OBBond *bond;
141
 
  vector<OBEdgeBase*>::iterator i;
142
 
  for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
143
 
    if (bond->IsCarbonyl())
144
 
      return(true);
145
 
  
146
 
  return(false);
 
145
    OBAtom *a1,*a2;
 
146
    a1 = a2 = NULL;
 
147
 
 
148
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
 
149
    {
 
150
        a1 = (OBAtom*)_bgn;
 
151
        a2 = (OBAtom*)_end;
 
152
    }
 
153
 
 
154
    if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
 
155
    {
 
156
        a1 = (OBAtom*)_end;
 
157
        a2 = (OBAtom*)_bgn;
 
158
    }
 
159
 
 
160
    if (!a1 || !a2)
 
161
        return(false);
 
162
    if (GetBO() != 1)
 
163
        return(false);
 
164
 
 
165
    OBBond *bond;
 
166
    vector<OBEdgeBase*>::iterator i;
 
167
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
 
168
        if (bond->IsCarbonyl())
 
169
            return(true);
 
170
 
 
171
    return(false);
147
172
}
148
173
 
149
174
bool OBBond::IsPrimaryAmide()
150
175
{
151
 
  OBAtom *a1,*a2;
152
 
  a1 = a2 = NULL;
153
 
 
154
 
  if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
155
 
    {a1 = (OBAtom*)_bgn; a2 = (OBAtom*)_end;}
156
 
 
157
 
  if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
158
 
    {a1 = (OBAtom*)_end; a2 = (OBAtom*)_bgn;}
159
 
 
160
 
  if (!a1 || !a2) return(false);
161
 
  if (GetBO() != 1) return(false);
162
 
  
163
 
  OBBond *bond;
164
 
  vector<OBEdgeBase*>::iterator i;
165
 
  for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
166
 
    if (bond->IsCarbonyl())
167
 
      if (a2->GetHvyValence() == 2)
168
 
      return(true);
169
 
 
170
 
  
171
 
  return(false);
 
176
    OBAtom *a1,*a2;
 
177
    a1 = a2 = NULL;
 
178
 
 
179
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7)
 
180
    {
 
181
        a1 = (OBAtom*)_bgn;
 
182
        a2 = (OBAtom*)_end;
 
183
    }
 
184
 
 
185
    if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6)
 
186
    {
 
187
        a1 = (OBAtom*)_end;
 
188
        a2 = (OBAtom*)_bgn;
 
189
    }
 
190
 
 
191
    if (!a1 || !a2)
 
192
        return(false);
 
193
    if (GetBO() != 1)
 
194
        return(false);
 
195
 
 
196
    OBBond *bond;
 
197
    vector<OBEdgeBase*>::iterator i;
 
198
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
 
199
        if (bond->IsCarbonyl())
 
200
            if (a2->GetHvyValence() == 2)
 
201
                return(true);
 
202
 
 
203
    return(false);
172
204
}
173
205
 
 
206
//! \todo Implement this properly -- currently always returns false
174
207
bool OBBond::IsSecondaryAmide()
175
208
{
176
 
  
177
 
  
178
 
  return(false);
 
209
    return(false);
179
210
}
180
211
 
181
212
bool OBBond::IsEster()
182
213
{
183
 
  OBAtom *a1,*a2;
184
 
  a1 = a2 = NULL;
185
 
 
186
 
  if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8)
187
 
    {a1 = (OBAtom*)_bgn; a2 = (OBAtom*)_end;}
188
 
 
189
 
  if (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6)
190
 
    {a1 = (OBAtom*)_end; a2 = (OBAtom*)_bgn;}
191
 
 
192
 
  if (!a1 || !a2) return(false);
193
 
  if (GetBO() != 1) return(false);
194
 
  
195
 
  OBBond *bond;
196
 
  vector<OBEdgeBase*>::iterator i;
197
 
  for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
198
 
    if (bond->IsCarbonyl())
199
 
      return(true);
200
 
  
201
 
  
202
 
  return(false);
 
214
    OBAtom *a1,*a2;
 
215
    a1 = a2 = NULL;
 
216
 
 
217
    if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8)
 
218
    {
 
219
        a1 = (OBAtom*)_bgn;
 
220
        a2 = (OBAtom*)_end;
 
221
    }
 
222
 
 
223
    if (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6)
 
224
    {
 
225
        a1 = (OBAtom*)_end;
 
226
        a2 = (OBAtom*)_bgn;
 
227
    }
 
228
 
 
229
    if (!a1 || !a2)
 
230
        return(false);
 
231
    if (GetBO() != 1)
 
232
        return(false);
 
233
 
 
234
    OBBond *bond;
 
235
    vector<OBEdgeBase*>::iterator i;
 
236
    for (bond = a1->BeginBond(i);bond;bond = a1->NextBond(i))
 
237
        if (bond->IsCarbonyl())
 
238
            return(true);
 
239
 
 
240
    return(false);
203
241
}
204
242
 
205
243
bool OBBond::IsCarbonyl()
206
244
{
207
 
  if (GetBO() != 2) return(false);
208
 
  
209
 
  if ((_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8) || 
210
 
      (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6))
211
 
    return(true);
212
 
 
213
 
  return(false);
 
245
    if (GetBO() != 2)
 
246
        return(false);
 
247
 
 
248
    if ((_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 8) ||
 
249
            (_bgn->GetAtomicNum() == 8 && _end->GetAtomicNum() == 6))
 
250
        return(true);
 
251
 
 
252
    return(false);
214
253
}
215
254
 
216
255
bool OBBond::IsSingle()
217
256
{
218
 
        if (HasFlag(OB_AROMATIC_BOND)) return(false);
219
 
 
220
 
        if (!((OBMol*)GetParent())->HasAromaticPerceived())
221
 
                {
222
 
                        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
223
 
                }
224
 
 
225
 
        if ((this->GetBondOrder()==1) && !(HasFlag(OB_AROMATIC_BOND)))
226
 
                return(true);
227
 
 
228
 
        return(false);
 
257
    if (HasFlag(OB_AROMATIC_BOND))
 
258
        return(false);
 
259
 
 
260
    if (!((OBMol*)GetParent())->HasAromaticPerceived())
 
261
    {
 
262
        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
 
263
    }
 
264
 
 
265
    if ((this->GetBondOrder()==1) && !(HasFlag(OB_AROMATIC_BOND)))
 
266
        return(true);
 
267
 
 
268
    return(false);
229
269
}
230
270
 
231
271
bool OBBond::IsDouble()
232
272
{
233
 
        if      (HasFlag(OB_AROMATIC_BOND)) return(false);
234
 
 
235
 
        if (!((OBMol*)GetParent())->HasAromaticPerceived())
236
 
                {
237
 
                        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
238
 
                }
239
 
                        
240
 
        if ((this->GetBondOrder()==2) && !(HasFlag(OB_AROMATIC_BOND)))
241
 
                return(true);
242
 
 
243
 
        return(false);
 
273
    if  (HasFlag(OB_AROMATIC_BOND))
 
274
        return(false);
 
275
 
 
276
    if (!((OBMol*)GetParent())->HasAromaticPerceived())
 
277
    {
 
278
        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
 
279
    }
 
280
 
 
281
    if ((this->GetBondOrder()==2) && !(HasFlag(OB_AROMATIC_BOND)))
 
282
        return(true);
 
283
 
 
284
    return(false);
244
285
}
245
286
 
246
287
bool OBBond::IsTriple()
247
288
{
248
 
        if      (HasFlag(OB_AROMATIC_BOND)) return(false);
249
 
 
250
 
        if (!((OBMol*)GetParent())->HasAromaticPerceived())
251
 
                {
252
 
                        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
253
 
                }
254
 
                        
255
 
        if ((this->GetBondOrder()==3) && !(HasFlag(OB_AROMATIC_BOND)))
256
 
                return(true);
257
 
 
258
 
        return(false);
 
289
    if  (HasFlag(OB_AROMATIC_BOND))
 
290
        return(false);
 
291
 
 
292
    if (!((OBMol*)GetParent())->HasAromaticPerceived())
 
293
    {
 
294
        aromtyper.AssignAromaticFlags(*((OBMol*)GetParent()));
 
295
    }
 
296
 
 
297
    if ((this->GetBondOrder()==3) && !(HasFlag(OB_AROMATIC_BOND)))
 
298
        return(true);
 
299
 
 
300
    return(false);
259
301
}
260
302
 
261
303
bool OBBond::IsAromatic() const
262
304
{
263
 
  if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND)) return(true);
 
305
    if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND))
 
306
        return(true);
264
307
 
265
 
  OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
266
 
  if (!mol->HasAromaticPerceived())
 
308
    OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
 
309
    if (!mol->HasAromaticPerceived())
267
310
    {
268
 
      aromtyper.AssignAromaticFlags(*mol);
269
 
      if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND)) return(true);
 
311
        aromtyper.AssignAromaticFlags(*mol);
 
312
        if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND))
 
313
            return(true);
270
314
    }
271
315
 
272
 
  return(false);
 
316
    return(false);
 
317
}
 
318
 
 
319
/*! This method checks if the geometry around this bond looks unsaturated
 
320
  by measuring the torsion angles formed by all connected atoms X-start=end-Y
 
321
  and checking that they are close to 0 or 180 degrees */
 
322
bool OBBond::IsDoubleBondGeometry()
 
323
{
 
324
  double torsion;
 
325
  OBAtom *nbrStart,*nbrEnd;
 
326
  vector<OBEdgeBase*>::iterator i,j;
 
327
  // We concentrate on sp2 atoms with valence up to 3 and ignore the rest (like sp1 or S,P)
 
328
  // As this is called from PerceiveBondOrders, GetHyb() may still be undefined.
 
329
  if (_bgn->GetHyb()==1 || _bgn->GetValence()>3||
 
330
      _end->GetHyb()==1 || _end->GetValence()>3)
 
331
    return(true);
 
332
 
 
333
  for (nbrStart = static_cast<OBAtom*>(_bgn)->BeginNbrAtom(i); nbrStart;
 
334
       nbrStart = static_cast<OBAtom*>(_bgn)->NextNbrAtom(i))
 
335
    {
 
336
      if (nbrStart != _end)
 
337
        { 
 
338
          for (nbrEnd = static_cast<OBAtom*>(_end)->BeginNbrAtom(j);
 
339
               nbrEnd; nbrEnd = static_cast<OBAtom*>(_end)->NextNbrAtom(j))
 
340
            {
 
341
              if (nbrEnd != _bgn)
 
342
                {
 
343
                  torsion=fabs(CalcTorsionAngle(nbrStart->GetVector(),
 
344
                                                static_cast<OBAtom*>(_bgn)->GetVector(),
 
345
                                                static_cast<OBAtom*>(_end)->GetVector(),
 
346
                                                nbrEnd->GetVector()));
 
347
 
 
348
                  // >12&&<168 not enough
 
349
                  if (torsion > 15.0f  && torsion < 165.0f)
 
350
                    {
 
351
                      // Geometry does not match a double bond
 
352
                      return(false);
 
353
                    }
 
354
 
 
355
                }
 
356
            }  // end loop for neighbors of end
 
357
        }
 
358
    } // end loop for neighbors of start
 
359
  return(true);
273
360
}
274
361
 
275
362
void OBBond::SetKSingle()
276
363
{
277
 
  _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
278
 
  _flags |= OB_KSINGLE_BOND;
 
364
    _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
 
365
    _flags |= OB_KSINGLE_BOND;
279
366
}
280
367
 
281
368
void OBBond::SetKDouble()
282
369
{
283
 
  _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
284
 
  _flags |= OB_KDOUBLE_BOND;
 
370
    _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
 
371
    _flags |= OB_KDOUBLE_BOND;
285
372
}
286
373
 
287
374
void OBBond::SetKTriple()
288
375
{
289
 
  _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
290
 
  _flags |= OB_KTRIPLE_BOND;
 
376
    _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
 
377
    _flags |= OB_KTRIPLE_BOND;
291
378
}
292
379
 
293
380
bool OBBond::IsKSingle()
294
381
{
295
 
  if (_flags & OB_KSINGLE_BOND) return(true);
296
 
  if (!((OBMol*)GetParent())->HasKekulePerceived()) 
297
 
          ((OBMol*)GetParent())->PerceiveKekuleBonds();
 
382
    if (_flags & OB_KSINGLE_BOND)
 
383
        return(true);
 
384
    if (!((OBMol*)GetParent())->HasKekulePerceived())
 
385
        ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
298
386
 
299
 
  return((_flags & OB_KSINGLE_BOND) != 0) ? true : false;
 
387
    return((_flags & OB_KSINGLE_BOND) != 0) ? true : false;
300
388
}
301
389
 
302
390
bool OBBond::IsKDouble()
303
391
{
304
 
  if (_flags & OB_KDOUBLE_BOND) return(true);
305
 
  if (!((OBMol*)GetParent())->HasKekulePerceived()) 
306
 
          ((OBMol*)GetParent())->PerceiveKekuleBonds();
 
392
    if (_flags & OB_KDOUBLE_BOND)
 
393
        return(true);
 
394
    if (!((OBMol*)GetParent())->HasKekulePerceived())
 
395
        ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
307
396
 
308
 
  return((_flags & OB_KDOUBLE_BOND) != 0) ? true : false;
 
397
    return((_flags & OB_KDOUBLE_BOND) != 0) ? true : false;
309
398
}
310
399
 
311
400
bool OBBond::IsKTriple()
312
401
{
313
 
  if (_flags & OB_KTRIPLE_BOND) return(true);
314
 
  if (!((OBMol*)GetParent())->HasKekulePerceived()) 
315
 
          ((OBMol*)GetParent())->PerceiveKekuleBonds();
 
402
    if (_flags & OB_KTRIPLE_BOND)
 
403
        return(true);
 
404
    if (!((OBMol*)GetParent())->HasKekulePerceived())
 
405
        ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
316
406
 
317
 
  return((_flags & OB_KTRIPLE_BOND) != 0) ? true : false;
 
407
    return((_flags & OB_KTRIPLE_BOND) != 0) ? true : false;
318
408
}
319
409
 
320
410
bool OBBond::IsInRing() const
321
411
{
322
 
  if (((OBBond*)this)->HasFlag(OB_RING_BOND)) return(true);
323
 
  
324
 
  OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
325
 
  if (!mol->HasRingAtomsAndBondsPerceived())
 
412
    if (((OBBond*)this)->HasFlag(OB_RING_BOND))
 
413
        return(true);
 
414
 
 
415
    OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
 
416
    if (!mol->HasRingAtomsAndBondsPerceived())
326
417
    {
327
 
      mol->FindRingAtomsAndBonds();
328
 
      if (((OBBond*)this)->HasFlag(OB_RING_BOND)) return(true);
 
418
        mol->FindRingAtomsAndBonds();
 
419
        if (((OBBond*)this)->HasFlag(OB_RING_BOND))
 
420
            return(true);
329
421
    }
330
422
 
331
 
  return(false);
 
423
    return(false);
332
424
}
333
425
 
334
426
bool OBBond::IsClosure()
335
427
{
336
 
  OBMol *mol = (OBMol*)GetParent();
337
 
  if (!mol) return(false);
338
 
  if (mol->HasClosureBondsPerceived()) return(HasFlag(OB_CLOSURE_BOND));
339
 
  
340
 
  mol->SetClosureBondsPerceived();
341
 
  
342
 
  OBBond *bond;
343
 
  OBAtom *atom,*nbr;
344
 
  OBBitVec uatoms,ubonds;
345
 
  vector<OBNodeBase*> curr,next;
346
 
  vector<OBNodeBase*>::iterator i;
347
 
  vector<OBEdgeBase*>::iterator j;
348
 
 
349
 
  uatoms.Resize(mol->NumAtoms()+1);
350
 
  ubonds.Resize(mol->NumAtoms()+1);
351
 
 
352
 
  for (;uatoms.CountBits() < (signed)mol->NumAtoms();)
 
428
    OBMol *mol = (OBMol*)GetParent();
 
429
    if (!mol)
 
430
        return(false);
 
431
    if (mol->HasClosureBondsPerceived())
 
432
        return(HasFlag(OB_CLOSURE_BOND));
 
433
 
 
434
    mol->SetClosureBondsPerceived();
 
435
 
 
436
    obErrorLog.ThrowError(__FUNCTION__,
 
437
                          "Ran OpenBabel::PerceiveClosureBonds", obAuditMsg);
 
438
 
 
439
    OBBond *bond;
 
440
    OBAtom *atom,*nbr;
 
441
    OBBitVec uatoms,ubonds;
 
442
    vector<OBNodeBase*> curr,next;
 
443
    vector<OBNodeBase*>::iterator i;
 
444
    vector<OBEdgeBase*>::iterator j;
 
445
 
 
446
    uatoms.Resize(mol->NumAtoms()+1);
 
447
    ubonds.Resize(mol->NumAtoms()+1);
 
448
 
 
449
    for (;uatoms.CountBits() < (signed)mol->NumAtoms();)
353
450
    {
354
 
      if (curr.empty())
355
 
        for (atom = mol->BeginAtom(i);atom;atom = mol->NextAtom(i))
356
 
          if (!uatoms[atom->GetIdx()])
357
 
            {
358
 
              uatoms |= atom->GetIdx();
359
 
              curr.push_back(atom);
360
 
              break;
361
 
            }
362
 
 
363
 
      for (;!curr.empty();)
364
 
        {
365
 
          for (i = curr.begin();i != curr.end();i++)
366
 
            for (nbr = ((OBAtom*)*i)->BeginNbrAtom(j);nbr;nbr = ((OBAtom*)*i)->NextNbrAtom(j))
367
 
              if (!uatoms[nbr->GetIdx()])
368
 
                {
369
 
                  uatoms |= nbr->GetIdx();
370
 
                  ubonds |= (*j)->GetIdx();
371
 
                  next.push_back(nbr);
372
 
                }
373
 
 
374
 
          curr = next;
375
 
          next.clear();
376
 
        }
 
451
        if (curr.empty())
 
452
            for (atom = mol->BeginAtom(i);atom;atom = mol->NextAtom(i))
 
453
                if (!uatoms[atom->GetIdx()])
 
454
                {
 
455
                    uatoms |= atom->GetIdx();
 
456
                    curr.push_back(atom);
 
457
                    break;
 
458
                }
 
459
 
 
460
        for (;!curr.empty();)
 
461
        {
 
462
            for (i = curr.begin();i != curr.end();i++)
 
463
                for (nbr = ((OBAtom*)*i)->BeginNbrAtom(j);nbr;nbr = ((OBAtom*)*i)->NextNbrAtom(j))
 
464
                    if (!uatoms[nbr->GetIdx()])
 
465
                    {
 
466
                        uatoms |= nbr->GetIdx();
 
467
                        ubonds |= (*j)->GetIdx();
 
468
                        next.push_back(nbr);
 
469
                    }
 
470
 
 
471
            curr = next;
 
472
            next.clear();
 
473
        }
377
474
    }
378
475
 
379
 
  for (bond = mol->BeginBond(j);bond;bond = mol->NextBond(j))
380
 
    if (!ubonds[bond->GetIdx()])
381
 
      bond->SetClosure();
382
 
  
383
 
  return(HasFlag(OB_CLOSURE_BOND));
 
476
    for (bond = mol->BeginBond(j);bond;bond = mol->NextBond(j))
 
477
        if (!ubonds[bond->GetIdx()])
 
478
            bond->SetClosure();
 
479
 
 
480
    return(HasFlag(OB_CLOSURE_BOND));
384
481
}
385
482
 
386
483
double OBBond::GetEquibLength()
387
484
{
388
 
  double length;
389
 
  OBAtom *begin, *end;
390
 
  // CorrectedBondRad will always return a # now
391
 
  //  if (!CorrectedBondRad(GetBeginAtom(),rad1)) return(0.0);
392
 
  //  if (!CorrectedBondRad(GetEndAtom(),rad2))   return(0.0);
393
 
 
394
 
  begin = GetBeginAtom();
395
 
  end = GetEndAtom();
396
 
  length = etab.CorrectedBondRad(begin->GetAtomicNum(), begin->GetHyb())
397
 
    + etab.CorrectedBondRad(end->GetAtomicNum(), end->GetHyb());
398
 
  
399
 
  if (IsAromatic()) length *= 0.93;
400
 
  else if (GetBO() == 2)         length *= 0.91;
401
 
  else if (GetBO() == 3)         length *= 0.87;
402
 
  return(length);
 
485
    double length;
 
486
    OBAtom *begin, *end;
 
487
    // CorrectedBondRad will always return a # now
 
488
    //  if (!CorrectedBondRad(GetBeginAtom(),rad1)) return(0.0);
 
489
    //  if (!CorrectedBondRad(GetEndAtom(),rad2))   return(0.0);
 
490
 
 
491
    begin = GetBeginAtom();
 
492
    end = GetEndAtom();
 
493
    length = etab.CorrectedBondRad(begin->GetAtomicNum(), begin->GetHyb())
 
494
             + etab.CorrectedBondRad(end->GetAtomicNum(), end->GetHyb());
 
495
 
 
496
    if (IsAromatic())
 
497
        length *= 0.93;
 
498
    else if (GetBO() == 2)
 
499
        length *= 0.91;
 
500
    else if (GetBO() == 3)
 
501
        length *= 0.87;
 
502
    return(length);
403
503
}
404
504
 
405
505
double OBBond::GetLength()
406
506
{
407
 
  double        d2;
408
 
  OBAtom *begin, *end;
409
 
  begin = GetBeginAtom();
410
 
  end = GetEndAtom();
411
 
  
412
 
  d2 = SQUARE(begin->GetX() - end->GetX());
413
 
  d2 += SQUARE(begin->GetY() - end->GetY());
414
 
  d2 += SQUARE(begin->GetZ() - end->GetZ());
415
 
 
416
 
  return(sqrt(d2));
 
507
    double      d2;
 
508
    OBAtom *begin, *end;
 
509
    begin = GetBeginAtom();
 
510
    end = GetEndAtom();
 
511
 
 
512
    d2 = SQUARE(begin->GetX() - end->GetX());
 
513
    d2 += SQUARE(begin->GetY() - end->GetY());
 
514
    d2 += SQUARE(begin->GetZ() - end->GetZ());
 
515
 
 
516
    return(sqrt(d2));
417
517
}
418
518
 
419
519
// OBGenericData methods
420
520
bool OBBond::HasData(string &s)
421
 
     //returns true if the generic attribute/value pair exists
 
521
//returns true if the generic attribute/value pair exists
422
522
{
423
 
  if (_vdata.empty()) return(false);
 
523
    if (_vdata.empty())
 
524
        return(false);
424
525
 
425
526
    vector<OBGenericData*>::iterator i;
426
527
 
427
528
    for (i = _vdata.begin();i != _vdata.end();i++)
428
529
        if ((*i)->GetAttribute() == s)
429
530
            return(true);
430
 
    
 
531
 
431
532
    return(false);
432
533
}
433
534
 
434
535
bool OBBond::HasData(const char *s)
435
 
     //returns true if the generic attribute/value pair exists
 
536
//returns true if the generic attribute/value pair exists
436
537
{
437
 
  if (_vdata.empty()) return(false);
 
538
    if (_vdata.empty())
 
539
        return(false);
438
540
 
439
541
    vector<OBGenericData*>::iterator i;
440
542
 
441
543
    for (i = _vdata.begin();i != _vdata.end();i++)
442
544
        if ((*i)->GetAttribute() == s)
443
545
            return(true);
444
 
    
 
546
 
445
547
    return(false);
446
548
}
447
549
 
448
 
bool OBBond::HasData(obDataType dt)
449
 
     //returns true if the generic attribute/value pair exists
 
550
bool OBBond::HasData(unsigned int dt)
 
551
//returns true if the generic attribute/value pair exists
450
552
{
451
 
  if (_vdata.empty()) return(false);
 
553
    if (_vdata.empty())
 
554
        return(false);
452
555
 
453
556
    vector<OBGenericData*>::iterator i;
454
557
 
455
558
    for (i = _vdata.begin();i != _vdata.end();i++)
456
559
        if ((*i)->GetDataType() == dt)
457
560
            return(true);
458
 
    
 
561
 
459
562
    return(false);
460
563
}
461
564
 
462
565
OBGenericData *OBBond::GetData(string &s)
463
 
     //returns the value given an attribute
 
566
//returns the value given an attribute
464
567
{
465
568
    vector<OBGenericData*>::iterator i;
466
569
 
467
570
    for (i = _vdata.begin();i != _vdata.end();i++)
468
 
                if ((*i)->GetAttribute() == s)
 
571
        if ((*i)->GetAttribute() == s)
469
572
            return(*i);
470
573
 
471
574
    return(NULL);
472
575
}
473
576
 
474
577
OBGenericData *OBBond::GetData(const char *s)
475
 
     //returns the value given an attribute
476
 
{
477
 
    vector<OBGenericData*>::iterator i;
478
 
 
479
 
    for (i = _vdata.begin();i != _vdata.end();i++)
480
 
                if ((*i)->GetAttribute() == s)
481
 
            return(*i);
482
 
 
483
 
    return(NULL);
484
 
}
485
 
 
486
 
OBGenericData *OBBond::GetData(obDataType dt)
487
 
{
488
 
    vector<OBGenericData*>::iterator i;
489
 
    for (i = _vdata.begin();i != _vdata.end();i++)
490
 
        if ((*i)->GetDataType() == dt)
491
 
            return(*i);
492
 
    return(NULL);
493
 
}
494
 
 
495
 
void OBBond::DeleteData(obDataType dt)
496
 
{
497
 
  vector<OBGenericData*> vdata;
498
 
  vector<OBGenericData*>::iterator i;
499
 
    for (i = _vdata.begin();i != _vdata.end();i++)
500
 
        if ((*i)->GetDataType() == dt) delete *i;
501
 
        else vdata.push_back(*i);
502
 
  _vdata = vdata;
 
578
//returns the value given an attribute
 
579
{
 
580
    vector<OBGenericData*>::iterator i;
 
581
 
 
582
    for (i = _vdata.begin();i != _vdata.end();i++)
 
583
        if ((*i)->GetAttribute() == s)
 
584
            return(*i);
 
585
 
 
586
    return(NULL);
 
587
}
 
588
 
 
589
OBGenericData *OBBond::GetData(unsigned int dt)
 
590
{
 
591
    vector<OBGenericData*>::iterator i;
 
592
    for (i = _vdata.begin();i != _vdata.end();i++)
 
593
        if ((*i)->GetDataType() == dt)
 
594
            return(*i);
 
595
    return(NULL);
 
596
}
 
597
 
 
598
void OBBond::DeleteData(unsigned int dt)
 
599
{
 
600
    vector<OBGenericData*> vdata;
 
601
    vector<OBGenericData*>::iterator i;
 
602
    for (i = _vdata.begin();i != _vdata.end();i++)
 
603
        if ((*i)->GetDataType() == dt)
 
604
            delete *i;
 
605
        else
 
606
            vdata.push_back(*i);
 
607
    _vdata = vdata;
503
608
}
504
609
 
505
610
void OBBond::DeleteData(vector<OBGenericData*> &vg)
506
611
{
507
 
  vector<OBGenericData*> vdata;
508
 
  vector<OBGenericData*>::iterator i,j;
 
612
    vector<OBGenericData*> vdata;
 
613
    vector<OBGenericData*>::iterator i,j;
509
614
 
510
 
  bool del;
511
 
  for (i = _vdata.begin();i != _vdata.end();i++)
512
 
  {
513
 
          del = false;
514
 
          for (j = vg.begin();j != vg.end();j++)
515
 
                  if (*i == *j)
516
 
                  {
517
 
                          del = true;
518
 
                          break;
519
 
                  }
520
 
           if (del) delete *i;
521
 
           else     vdata.push_back(*i);
522
 
  }
523
 
  _vdata = vdata;
 
615
    bool del;
 
616
    for (i = _vdata.begin();i != _vdata.end();i++)
 
617
    {
 
618
        del = false;
 
619
        for (j = vg.begin();j != vg.end();j++)
 
620
            if (*i == *j)
 
621
            {
 
622
                del = true;
 
623
                break;
 
624
            }
 
625
        if (del)
 
626
            delete *i;
 
627
        else
 
628
            vdata.push_back(*i);
 
629
    }
 
630
    _vdata = vdata;
524
631
}
525
632
 
526
633
void OBBond::DeleteData(OBGenericData *gd)
527
634
{
528
 
  vector<OBGenericData*>::iterator i;
529
 
  for (i = _vdata.begin();i != _vdata.end();i++)
530
 
          if (*i == gd)
531
 
          {
532
 
                delete *i;
533
 
                _vdata.erase(i);
534
 
          }
535
 
 
536
 
}
537
 
 
538
 
}
 
635
    vector<OBGenericData*>::iterator i;
 
636
    for (i = _vdata.begin();i != _vdata.end();i++)
 
637
        if (*i == gd)
 
638
        {
 
639
            delete *i;
 
640
            _vdata.erase(i);
 
641
        }
 
642
 
 
643
}
 
644
 
 
645
} // end namespace OpenBabel
 
646
 
 
647
//! \file bond.cpp
 
648
//! \brief Handle OBBond class