ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/obbond.cpp
Revision: 2466
Committed: Wed Nov 23 01:05:59 2005 UTC (18 years, 7 months ago) by chuckv
File size: 15363 byte(s)
Log Message:
Changed file names that conflict w/ oopse file name object files.

File Contents

# User Rev Content
1 chuckv 2466 /**********************************************************************
2     bond.cpp - Handle OBBond class
3    
4     Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5     Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6    
7     This file is part of the Open Babel project.
8     For more information, see <http://openbabel.sourceforge.net/>
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    
20     #include "mol.hpp"
21     #include "typer.hpp"
22    
23     using namespace std;
24    
25     namespace OpenBabel
26     {
27    
28     extern OBAromaticTyper aromtyper;
29    
30     /** \class OBBond
31     \brief Bond class
32    
33     The OBBond class is straightforward in its data access and
34     modification methods. OBBonds store pointers to the atoms on each end
35     of the bond. In storing pointers to atoms instead of integer indices,
36     the necessity of having to reorder bonds when atoms are shuffled,
37     added, or delete is obviated.
38     */
39    
40     // *******************************
41     // *** OBBond member functions ***
42     // *******************************
43    
44     OBBond::OBBond()
45     {
46     _idx=0;
47     _order=0;
48     _flags=0;
49     _bgn=NULL;
50     _end=NULL;
51     _vdata.clear();
52     }
53    
54     OBBond::~OBBond()
55     {
56     if (!_vdata.empty())
57     {
58     vector<OBGenericData*>::iterator m;
59     for (m = _vdata.begin();m != _vdata.end();m++)
60     delete *m;
61     _vdata.clear();
62     }
63     }
64    
65     void OBBond::Set(int idx,OBAtom *begin,OBAtom *end,int order,int flags)
66     {
67     SetIdx(idx);
68     SetBegin(begin);
69     SetEnd(end);
70     SetBO(order);
71     SetFlag(flags);
72     }
73    
74     void OBBond::SetBO(int order)
75     {
76     _order = (char)order;
77     if (order == 5)
78     {
79     SetAromatic();
80     if (_bgn)
81     _bgn->SetAromatic();
82     if (_end)
83     _end->SetAromatic();
84     }
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     }
96     }
97    
98     void OBBond::SetLength(OBAtom *fixed, double length)
99     {
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++ )
123     {
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     */
133     }
134     }
135    
136     bool OBBond::IsRotor()
137     {
138     return(_bgn->GetHvyValence() > 1 && _end->GetHvyValence() > 1 &&
139     _order == 1 && !IsInRing() && _bgn->GetHyb() != 1 &&
140     _end->GetHyb() != 1);
141     }
142    
143     bool OBBond::IsAmide()
144     {
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);
172     }
173    
174     bool OBBond::IsPrimaryAmide()
175     {
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);
204     }
205    
206     //! \todo Implement this properly -- currently always returns false
207     bool OBBond::IsSecondaryAmide()
208     {
209     return(false);
210     }
211    
212     bool OBBond::IsEster()
213     {
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);
241     }
242    
243     bool OBBond::IsCarbonyl()
244     {
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);
253     }
254    
255     bool OBBond::IsSingle()
256     {
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);
269     }
270    
271     bool OBBond::IsDouble()
272     {
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);
285     }
286    
287     bool OBBond::IsTriple()
288     {
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);
301     }
302    
303     bool OBBond::IsAromatic() const
304     {
305     if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND))
306     return(true);
307    
308     OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
309     if (!mol->HasAromaticPerceived())
310     {
311     aromtyper.AssignAromaticFlags(*mol);
312     if (((OBBond*)this)->HasFlag(OB_AROMATIC_BOND))
313     return(true);
314     }
315    
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);
360     }
361    
362     void OBBond::SetKSingle()
363     {
364     _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
365     _flags |= OB_KSINGLE_BOND;
366     }
367    
368     void OBBond::SetKDouble()
369     {
370     _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
371     _flags |= OB_KDOUBLE_BOND;
372     }
373    
374     void OBBond::SetKTriple()
375     {
376     _flags &= (~(OB_KSINGLE_BOND|OB_KDOUBLE_BOND|OB_KTRIPLE_BOND));
377     _flags |= OB_KTRIPLE_BOND;
378     }
379    
380     bool OBBond::IsKSingle()
381     {
382     if (_flags & OB_KSINGLE_BOND)
383     return(true);
384     if (!((OBMol*)GetParent())->HasKekulePerceived())
385     ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
386    
387     return((_flags & OB_KSINGLE_BOND) != 0) ? true : false;
388     }
389    
390     bool OBBond::IsKDouble()
391     {
392     if (_flags & OB_KDOUBLE_BOND)
393     return(true);
394     if (!((OBMol*)GetParent())->HasKekulePerceived())
395     ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
396    
397     return((_flags & OB_KDOUBLE_BOND) != 0) ? true : false;
398     }
399    
400     bool OBBond::IsKTriple()
401     {
402     if (_flags & OB_KTRIPLE_BOND)
403     return(true);
404     if (!((OBMol*)GetParent())->HasKekulePerceived())
405     ((OBMol*)GetParent())->NewPerceiveKekuleBonds();
406    
407     return((_flags & OB_KTRIPLE_BOND) != 0) ? true : false;
408     }
409    
410     bool OBBond::IsInRing() const
411     {
412     if (((OBBond*)this)->HasFlag(OB_RING_BOND))
413     return(true);
414    
415     OBMol *mol = (OBMol*)((OBBond*)this)->GetParent();
416     if (!mol->HasRingAtomsAndBondsPerceived())
417     {
418     mol->FindRingAtomsAndBonds();
419     if (((OBBond*)this)->HasFlag(OB_RING_BOND))
420     return(true);
421     }
422    
423     return(false);
424     }
425    
426     bool OBBond::IsClosure()
427     {
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();)
450     {
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     }
474     }
475    
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));
481     }
482    
483     double OBBond::GetEquibLength()
484     {
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);
503     }
504    
505     double OBBond::GetLength()
506     {
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));
517     }
518    
519     // OBGenericData methods
520     bool OBBond::HasData(string &s)
521     //returns true if the generic attribute/value pair exists
522     {
523     if (_vdata.empty())
524     return(false);
525    
526     vector<OBGenericData*>::iterator i;
527    
528     for (i = _vdata.begin();i != _vdata.end();i++)
529     if ((*i)->GetAttribute() == s)
530     return(true);
531    
532     return(false);
533     }
534    
535     bool OBBond::HasData(const char *s)
536     //returns true if the generic attribute/value pair exists
537     {
538     if (_vdata.empty())
539     return(false);
540    
541     vector<OBGenericData*>::iterator i;
542    
543     for (i = _vdata.begin();i != _vdata.end();i++)
544     if ((*i)->GetAttribute() == s)
545     return(true);
546    
547     return(false);
548     }
549    
550     bool OBBond::HasData(unsigned int dt)
551     //returns true if the generic attribute/value pair exists
552     {
553     if (_vdata.empty())
554     return(false);
555    
556     vector<OBGenericData*>::iterator i;
557    
558     for (i = _vdata.begin();i != _vdata.end();i++)
559     if ((*i)->GetDataType() == dt)
560     return(true);
561    
562     return(false);
563     }
564    
565     OBGenericData *OBBond::GetData(string &s)
566     //returns the value given an attribute
567     {
568     vector<OBGenericData*>::iterator i;
569    
570     for (i = _vdata.begin();i != _vdata.end();i++)
571     if ((*i)->GetAttribute() == s)
572     return(*i);
573    
574     return(NULL);
575     }
576    
577     OBGenericData *OBBond::GetData(const char *s)
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;
608     }
609    
610     void OBBond::DeleteData(vector<OBGenericData*> &vg)
611     {
612     vector<OBGenericData*> vdata;
613     vector<OBGenericData*>::iterator i,j;
614    
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;
631     }
632    
633     void OBBond::DeleteData(OBGenericData *gd)
634     {
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