ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/obutil.cpp
Revision: 3057
Committed: Thu Oct 19 20:49:05 2006 UTC (17 years, 11 months ago) by gezelter
File size: 32501 byte(s)
Log Message:
updated OpenBabel to version 2.0.2

File Contents

# User Rev Content
1 tim 2440 /**********************************************************************
2     obutil.cpp - Various utility methods.
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 gezelter 2450 #include "config.h"
21 tim 2440 #include "matrix3x3.hpp"
22     #include "vector3.hpp"
23     #include "mol.hpp"
24     #include "obutil.hpp"
25    
26     #if HAVE_CONIO_H
27     #include <conio.h>
28     #endif
29    
30     using namespace std;
31     namespace OpenBabel
32     {
33    
34 gezelter 3057 /*! \class OBStopwatch
35     \brief Stopwatch class used for timing length of execution
36 tim 2440
37 gezelter 3057 The OBStopwatch class makes timing the execution of blocks of
38     code to microsecond accuracy very simple. The class effectively
39     has two functions, Start() and Elapsed(). The usage of the
40     OBStopwatch class is demonstrated by the following code:
41     \code
42     OBStopwatch sw;
43     sw.Start();
44     //insert code here
45     cout << "Elapsed time = " << sw.Elapsed() << endl;
46     \endcode
47     */
48 tim 2440
49 gezelter 3057 //! Deprecated: use the OBMessageHandler class instead
50     //! \deprecated Throw an error through the OpenBabel::OBMessageHandler class
51     OBAPI void ThrowError(char *str)
52     {
53     obErrorLog.ThrowError("", str, obInfo);
54     }
55 tim 2440
56 gezelter 3057 //! Deprecated: use the OBMessageHandler class instead
57     //! \deprecated Throw an error through the OpenBabel::OBMessageHandler class
58     OBAPI void ThrowError(std::string &str)
59     {
60     obErrorLog.ThrowError("", str, obInfo);
61     }
62 tim 2440
63 gezelter 3057 // Comparison function (for sorting ints) returns a < b
64     OBAPI bool OBCompareInt(const int &a,const int &b)
65     {
66 tim 2440 return(a<b);
67 gezelter 3057 }
68 tim 2440
69 gezelter 3057 // Comparison function (for sorting unsigned ints) returns a < b
70     OBAPI bool OBCompareUnsigned(const unsigned int &a,const unsigned int &b)
71     {
72 tim 2440 return(a<b);
73 gezelter 3057 }
74 tim 2440
75 gezelter 3057 // Comparison for doubles: returns a < (b + epsilon)
76     OBAPI bool IsNear(const double &a, const double &b, const double epsilon)
77     {
78 tim 2440 return (fabs(a - b) < epsilon);
79 gezelter 3057 }
80 tim 2440
81 gezelter 3057 // Comparison for doubles: returns a < (0.0 + epsilon)
82     OBAPI bool IsNearZero(const double &a, const double epsilon)
83     {
84 tim 2440 return (fabs(a) < epsilon);
85 gezelter 3057 }
86 tim 2440
87 gezelter 3057 //! Utility function: replace the last extension in string &src with new extension char *ext.
88     OBAPI string NewExtension(string &src,char *ext)
89     {
90 tim 2440 unsigned int pos = (unsigned int)src.find_last_of(".");
91     string dst;
92    
93     if (pos != string::npos)
94 gezelter 3057 dst = src.substr(0,pos+1);
95 tim 2440 else
96 gezelter 3057 {
97 tim 2440 dst = src;
98     dst += ".";
99 gezelter 3057 }
100 tim 2440
101     dst += ext;
102     return(dst);
103 gezelter 3057 }
104 tim 2440
105 gezelter 3057 //! Return the geometric centroid to an array of coordinates in double* format
106     //! and center the coordinates to the origin. Operates on the first "size"
107     //! coordinates in the array.
108     OBAPI vector3 center_coords(double *c, unsigned int size)
109     {
110     if (size == 0)
111     {
112     vector3 v(0.0f, 0.0f, 0.0f);
113     return(v);
114     }
115 tim 2440 unsigned int i;
116     double x=0,y=0,z=0;
117     for (i = 0;i < size;i++)
118 gezelter 3057 {
119 tim 2440 x += c[i*3];
120     y += c[i*3+1];
121     z += c[i*3+2];
122 gezelter 3057 }
123 tim 2440 x /= (double) size;
124     y /= (double) size;
125     z /= (double) size;
126     for (i = 0;i < size;i++)
127 gezelter 3057 {
128 tim 2440 c[i*3] -= x;
129     c[i*3+1] -= y;
130     c[i*3+2] -= z;
131 gezelter 3057 }
132 tim 2440 vector3 v(x,y,z);
133     return(v);
134 gezelter 3057 }
135 tim 2440
136 gezelter 3057 //! Rotates the coordinate set *c by the transformation matrix m[3][3]
137     //! Operates on the first "size" coordinates in the array.
138     OBAPI void rotate_coords(double *c,double m[3][3],unsigned int size)
139     {
140 tim 2440 double x,y,z;
141     for (unsigned int i = 0;i < size;i++)
142 gezelter 3057 {
143 tim 2440 x = c[i*3]*m[0][0] + c[i*3+1]*m[0][1] + c[i*3+2]*m[0][2];
144     y = c[i*3]*m[1][0] + c[i*3+1]*m[1][1] + c[i*3+2]*m[1][2];
145     z = c[i*3]*m[2][0] + c[i*3+1]*m[2][1] + c[i*3+2]*m[2][2];
146     c[i*3] = x;
147     c[i*3+1] = y;
148     c[i*3+2] = z;
149 gezelter 3057 }
150     }
151 tim 2440
152 gezelter 3057 //! Calculate the RMS deviation between the first N coordinates of *r and *f
153     OBAPI double calc_rms(double *r,double *f, unsigned int N)
154     {
155     if (N == 0)
156     return 0.0f; // no RMS deviation between two empty sets
157 tim 2440
158     double d2=0.0;
159     for (unsigned int i = 0;i < N;i++)
160 gezelter 3057 {
161 tim 2440 d2 += SQUARE(r[i*3] - f[i*3]) +
162 gezelter 3057 SQUARE(r[i*3+1] - f[i*3+1]) +
163     SQUARE(r[i*3+2] - f[i*3+2]);
164     }
165 tim 2440
166     d2 /= (double) N;
167     return(sqrt(d2));
168 gezelter 3057 }
169 tim 2440
170 gezelter 3057 //! Rotate the coordinates of 'atoms'
171     //! such that tor == ang - atoms in 'tor' should be ordered such
172     //! that the 3rd atom is the pivot around which atoms rotate
173     OBAPI void SetRotorToAngle(double *c,vector<int> &tor,double ang,vector<int> &atoms)
174     {
175 tim 2440 double v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z;
176     double c1x,c1y,c1z,c2x,c2y,c2z,c3x,c3y,c3z;
177     double c1mag,c2mag,radang,costheta,m[9];
178     double x,y,z,mag,rotang,sn,cs,t,tx,ty,tz;
179    
180     //
181     //calculate the torsion angle
182     //
183     v1x = c[tor[0]] - c[tor[1]];
184     v2x = c[tor[1]] - c[tor[2]];
185     v1y = c[tor[0]+1] - c[tor[1]+1];
186     v2y = c[tor[1]+1] - c[tor[2]+1];
187     v1z = c[tor[0]+2] - c[tor[1]+2];
188     v2z = c[tor[1]+2] - c[tor[2]+2];
189     v3x = c[tor[2]] - c[tor[3]];
190     v3y = c[tor[2]+1] - c[tor[3]+1];
191     v3z = c[tor[2]+2] - c[tor[3]+2];
192    
193     c1x = v1y*v2z - v1z*v2y;
194     c2x = v2y*v3z - v2z*v3y;
195     c1y = -v1x*v2z + v1z*v2x;
196     c2y = -v2x*v3z + v2z*v3x;
197     c1z = v1x*v2y - v1y*v2x;
198     c2z = v2x*v3y - v2y*v3x;
199     c3x = c1y*c2z - c1z*c2y;
200     c3y = -c1x*c2z + c1z*c2x;
201     c3z = c1x*c2y - c1y*c2x;
202    
203     c1mag = SQUARE(c1x)+SQUARE(c1y)+SQUARE(c1z);
204     c2mag = SQUARE(c2x)+SQUARE(c2y)+SQUARE(c2z);
205     if (c1mag*c2mag < 0.01)
206 gezelter 3057 costheta = 1.0; //avoid div by zero error
207 tim 2440 else
208 gezelter 3057 costheta = (c1x*c2x + c1y*c2y + c1z*c2z)/(sqrt(c1mag*c2mag));
209 tim 2440
210     if (costheta < -0.999999)
211 gezelter 3057 costheta = -0.999999;
212 tim 2440 if (costheta > 0.999999)
213 gezelter 3057 costheta = 0.999999;
214 tim 2440
215     if ((v2x*c3x + v2y*c3y + v2z*c3z) > 0.0)
216 gezelter 3057 radang = -acos(costheta);
217 tim 2440 else
218 gezelter 3057 radang = acos(costheta);
219 tim 2440
220     //
221     // now we have the torsion angle (radang) - set up the rot matrix
222     //
223    
224     //find the difference between current and requested
225     rotang = ang - radang;
226    
227     sn = sin(rotang);
228     cs = cos(rotang);
229     t = 1 - cs;
230     //normalize the rotation vector
231     mag = sqrt(SQUARE(v2x)+SQUARE(v2y)+SQUARE(v2z));
232     x = v2x/mag;
233     y = v2y/mag;
234     z = v2z/mag;
235    
236     //set up the rotation matrix
237     m[0]= t*x*x + cs;
238     m[1] = t*x*y + sn*z;
239     m[2] = t*x*z - sn*y;
240     m[3] = t*x*y - sn*z;
241     m[4] = t*y*y + cs;
242     m[5] = t*y*z + sn*x;
243     m[6] = t*x*z + sn*y;
244     m[7] = t*y*z - sn*x;
245     m[8] = t*z*z + cs;
246    
247     //
248     //now the matrix is set - time to rotate the atoms
249     //
250     tx = c[tor[1]];
251     ty = c[tor[1]+1];
252     tz = c[tor[1]+2];
253     vector<int>::iterator i;
254     int j;
255     for (i = atoms.begin();i != atoms.end();i++)
256 gezelter 3057 {
257 tim 2440 j = *i;
258     c[j] -= tx;
259     c[j+1] -= ty;
260     c[j+2]-= tz;
261     x = c[j]*m[0] + c[j+1]*m[1] + c[j+2]*m[2];
262     y = c[j]*m[3] + c[j+1]*m[4] + c[j+2]*m[5];
263     z = c[j]*m[6] + c[j+1]*m[7] + c[j+2]*m[8];
264     c[j] = x;
265     c[j+1] = y;
266     c[j+2] = z;
267     c[j] += tx;
268     c[j+1] += ty;
269     c[j+2] += tz;
270 gezelter 3057 }
271     }
272 tim 2440
273 gezelter 3057 //! Safely open the supplied filename and return an ifstream, throwing an error
274     //! to the default OBMessageHandler error log if it fails.
275     OBAPI bool SafeOpen(ifstream &fs,char *filename)
276     {
277 tim 2440 #ifdef WIN32
278     string s = filename;
279     if (s.find(".bin") != string::npos)
280 gezelter 3057 fs.open(filename,ios::binary);
281 tim 2440 else
282     #endif
283    
284 gezelter 3057 fs.open(filename);
285 tim 2440
286     if (!fs)
287 gezelter 3057 {
288 tim 2440 string error = "Unable to open file \'";
289     error += filename;
290     error += "\' in read mode";
291 tim 2518 obErrorLog.ThrowError(__func__, error, obError);
292 tim 2440 return(false);
293 gezelter 3057 }
294 tim 2440
295     return(true);
296 gezelter 3057 }
297 tim 2440
298    
299 gezelter 3057 //! Safely open the supplied filename and return an ofstream, throwing an error
300     //! to the default OBMessageHandler error log if it fails.
301     OBAPI bool SafeOpen(ofstream &fs,char *filename)
302     {
303 tim 2440 #ifdef WIN32
304     string s = filename;
305     if (s.find(".bin") != string::npos)
306 gezelter 3057 fs.open(filename,ios::binary);
307 tim 2440 else
308     #endif
309    
310 gezelter 3057 fs.open(filename);
311 tim 2440
312     if (!fs)
313 gezelter 3057 {
314 tim 2440 string error = "Unable to open file \'";
315     error += filename;
316     error += "\' in write mode";
317 tim 2518 obErrorLog.ThrowError(__func__, error, obError);
318 tim 2440 return(false);
319 gezelter 3057 }
320 tim 2440
321     return(true);
322 gezelter 3057 }
323 tim 2440
324 gezelter 3057 //! Safely open the supplied filename and return an ifstream, throwing an error
325     //! to the default OBMessageHandler error log if it fails.
326     OBAPI bool SafeOpen(ifstream &fs,string &filename)
327     {
328 tim 2440 return(SafeOpen(fs,(char*)filename.c_str()));
329 gezelter 3057 }
330 tim 2440
331 gezelter 3057 //! Safely open the supplied filename and return an ofstream, throwing an error
332     //! to the default OBMessageHandler error log if it fails.
333     OBAPI bool SafeOpen(ofstream &fs,string &filename)
334     {
335 tim 2440 return(SafeOpen(fs,(char*)filename.c_str()));
336 gezelter 3057 }
337 tim 2440
338 gezelter 3057 //! Shift the supplied string to uppercase
339     OBAPI void ToUpper(std::string &s)
340     {
341 tim 2440 if (s.empty())
342 gezelter 3057 return;
343 tim 2440 unsigned int i;
344     for (i = 0;i < s.size();i++)
345 gezelter 3057 if (isalpha(s[i]) && !isdigit(s[i]))
346     s[i] = toupper(s[i]);
347     }
348 tim 2440
349 gezelter 3057 //! Shift the supplied char* to uppercase
350     OBAPI void ToUpper(char *cptr)
351     {
352 tim 2440 char *c;
353     for (c = cptr;*c != '\0';c++)
354 gezelter 3057 if (isalpha(*c) && !isdigit(*c))
355     *c = toupper(*c);
356     }
357 tim 2440
358 gezelter 3057 //! Shift the supplied string to lowercase
359     OBAPI void ToLower(std::string &s)
360     {
361 tim 2440 if (s.empty())
362 gezelter 3057 return;
363 tim 2440 unsigned int i;
364     for (i = 0;i < s.size();i++)
365 gezelter 3057 if (isalpha(s[i]) && !isdigit(s[i]))
366     s[i] = tolower(s[i]);
367     }
368 tim 2440
369 gezelter 3057 //! Shift the supplied char* to lowercase
370     OBAPI void ToLower(char *cptr)
371     {
372 tim 2440 char *c;
373     for (c = cptr;*c != '\0';c++)
374 gezelter 3057 if (isalpha(*c) && !isdigit(*c))
375     *c = tolower(*c);
376     }
377 tim 2440
378 gezelter 3057 //! "Clean" the supplied atom type, shifting the first character to uppercase,
379     //! the second character (if it's a letter) to lowercase, and terminating with a NULL
380     //! to strip off any trailing characters
381     OBAPI void CleanAtomType(char *id)
382     {
383 tim 2440 id[0] = toupper(id[0]);
384     if (isalpha(id[1]) == 0)
385 gezelter 3057 id[1] = '\0';
386 tim 2440 else
387     {
388 gezelter 3057 id[1] = tolower(id[1]);
389 tim 2440 id[2] = '\0';
390     }
391 gezelter 3057 }
392 tim 2440
393 gezelter 3057 //! Transform the supplied vector<OBInternalCoord*> into cartesian and update
394     //! the OBMol accordingly.
395     //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#zmatrixCoordinatesIntoCartesianCoordinates">blue-obelisk:zmatrixCoordinatesIntoCartesianCoordinates</a>
396     OBAPI void InternalToCartesian(std::vector<OBInternalCoord*> &vic,OBMol &mol)
397     {
398 tim 2440 vector3 n,nn,v1,v2,v3,avec,bvec,cvec;
399     double dst = 0.0, ang = 0.0, tor = 0.0;
400     OBAtom *atom;
401     vector<OBNodeBase*>::iterator i;
402     int index;
403    
404     if (vic.empty())
405 gezelter 3057 return;
406 tim 2440
407 tim 2518 obErrorLog.ThrowError(__func__,
408 tim 2440 "Ran OpenBabel::InternalToCartesian", obAuditMsg);
409    
410     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
411 gezelter 3057 {
412 tim 2440 index = atom->GetIdx();
413    
414 gezelter 3057 // make sure we always have valid pointers
415     if (index >= vic.size() || !vic[index])
416     return;
417 tim 2440
418     if (vic[index]->_a) // make sure we have a valid ptr
419 gezelter 3057 {
420 tim 2440 avec = vic[index]->_a->GetVector();
421     dst = vic[index]->_dst;
422 gezelter 3057 }
423 tim 2440 else
424 gezelter 3057 {
425 tim 2440 // atom 1
426     atom->SetVector(0.0, 0.0, 0.0);
427     continue;
428 gezelter 3057 }
429 tim 2440
430     if (vic[index]->_b)
431 gezelter 3057 {
432 tim 2440 bvec = vic[index]->_b->GetVector();
433     ang = vic[index]->_ang * DEG_TO_RAD;
434 gezelter 3057 }
435 tim 2440 else
436 gezelter 3057 {
437 tim 2440 // atom 2
438     atom->SetVector(dst, 0.0, 0.0);
439     continue;
440 gezelter 3057 }
441 tim 2440
442     if (vic[index]->_c)
443 gezelter 3057 {
444 tim 2440 cvec = vic[index]->_c->GetVector();
445     tor = vic[index]->_tor * DEG_TO_RAD;
446 gezelter 3057 }
447 tim 2440 else
448 gezelter 3057 {
449 tim 2440 // atom 3
450     cvec = VY;
451 gezelter 3057 tor = 90.0 * DEG_TO_RAD;
452     }
453 tim 2440
454     v1 = avec - bvec;
455     v2 = avec - cvec;
456     n = cross(v1,v2);
457     nn = cross(v1,n);
458     n.normalize();
459     nn.normalize();
460    
461     n *= -sin(tor);
462     nn *= cos(tor);
463     v3 = n + nn;
464     v3.normalize();
465     v3 *= dst * sin(ang);
466     v1.normalize();
467     v1 *= dst * cos(ang);
468     v2 = avec + v3 - v1;
469    
470     atom->SetVector(v2);
471 gezelter 3057 }
472 tim 2440
473     // Delete dummy atoms
474     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
475 gezelter 3057 if (atom->GetAtomicNum() == 0)
476     mol.DeleteAtom(atom);
477     }
478 tim 2440
479 gezelter 3057 //! Use the supplied OBMol and its Cartesian coordinates to generate
480     //! a set of internal (z-matrix) coordinates as supplied in the
481     //! vector<OBInternalCoord*> argument.
482     //! Implements <a href="http://qsar.sourceforge.net/dicts/blue-obelisk/index.xhtml#cartesianCoordinatesIntoZmatrixCoordinates">blue-obelisk:cartesianCoordinatesIntoZmatrixCoordinates</a>.
483     OBAPI void CartesianToInternal(std::vector<OBInternalCoord*> &vic,OBMol &mol)
484     {
485 tim 2440 double r,sum;
486     OBAtom *atom,*nbr,*ref;
487     vector<OBNodeBase*>::iterator i,j,m;
488    
489 tim 2518 obErrorLog.ThrowError(__func__,
490 tim 2440 "Ran OpenBabel::CartesianToInternal", obAuditMsg);
491    
492     //set reference atoms
493     for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
494 gezelter 3057 {
495 tim 2440 if (atom->GetIdx() == 1)
496 gezelter 3057 continue;
497 tim 2440 else if (atom->GetIdx() == 2)
498 gezelter 3057 {
499 tim 2440 vic[atom->GetIdx()]->_a = mol.GetAtom(1);
500     continue;
501 gezelter 3057 }
502 tim 2440 else if (atom->GetIdx() == 3)
503 gezelter 3057 {
504 tim 2440 if( (atom->GetVector()-mol.GetAtom(2)->GetVector()).length_2()
505 gezelter 3057 <(atom->GetVector()-mol.GetAtom(1)->GetVector()).length_2())
506     {
507 tim 2440 vic[atom->GetIdx()]->_a = mol.GetAtom(2);
508     vic[atom->GetIdx()]->_b = mol.GetAtom(1);
509 gezelter 3057 }
510 tim 2440 else
511 gezelter 3057 {
512 tim 2440 vic[atom->GetIdx()]->_a = mol.GetAtom(1);
513     vic[atom->GetIdx()]->_b = mol.GetAtom(2);
514 gezelter 3057 }
515 tim 2440 continue;
516 gezelter 3057 }
517 tim 2440 sum=1.0E10;
518     ref = mol.GetAtom(1);
519     for(nbr = mol.BeginAtom(j);nbr && (i != j);nbr = mol.NextAtom(j))
520 gezelter 3057 {
521 tim 2440 r = (atom->GetVector()-nbr->GetVector()).length_2();
522     if((r < sum) && (vic[nbr->GetIdx()]->_a != nbr) &&
523 gezelter 3057 (vic[nbr->GetIdx()]->_b != nbr))
524     {
525 tim 2440 sum = r;
526     ref = nbr;
527 gezelter 3057 }
528     }
529 tim 2440
530     vic[atom->GetIdx()]->_a = ref;
531     if (ref->GetIdx() >= 3)
532 gezelter 3057 {
533 tim 2440 vic[atom->GetIdx()]->_b = vic[ref->GetIdx()]->_a;
534     vic[atom->GetIdx()]->_c = vic[ref->GetIdx()]->_b;
535 gezelter 3057 }
536 tim 2440 else
537 gezelter 3057 {
538 tim 2440 if(ref->GetIdx()== 1)
539 gezelter 3057 {
540 tim 2440 vic[atom->GetIdx()]->_b = mol.GetAtom(2);
541     vic[atom->GetIdx()]->_c = mol.GetAtom(3);
542 gezelter 3057 }
543 tim 2440 else
544 gezelter 3057 {//ref->GetIdx()== 2
545 tim 2440 vic[atom->GetIdx()]->_b = mol.GetAtom(1);
546     vic[atom->GetIdx()]->_c = mol.GetAtom(3);
547 gezelter 3057 }
548     }
549     }
550 tim 2440
551     //fill in geometries
552     unsigned int k;
553     vector3 v1,v2;
554     OBAtom *a,*b,*c;
555     for (k = 2;k <= mol.NumAtoms();k++)
556 gezelter 3057 {
557 tim 2440 atom = mol.GetAtom(k);
558     a = vic[k]->_a;
559     b = vic[k]->_b;
560     c = vic[k]->_c;
561     if (k == 2)
562 gezelter 3057 {
563 tim 2440 vic[k]->_dst = (atom->GetVector() - a->GetVector()).length();
564     continue;
565 gezelter 3057 }
566 tim 2440
567     v1 = atom->GetVector() - a->GetVector();
568     v2 = b->GetVector() - a->GetVector();
569     vic[k]->_dst = v1.length();
570     vic[k]->_ang = vectorAngle(v1,v2);
571    
572     if (k == 3)
573 gezelter 3057 continue;
574 tim 2440 vic[k]->_tor = CalcTorsionAngle(atom->GetVector(),
575     a->GetVector(),
576     b->GetVector(),
577     c->GetVector());
578 gezelter 3057 }
579 tim 2440
580     //check for linear geometries and try to correct if possible
581     bool done;
582     double ang;
583     for (k = 2;k <= mol.NumAtoms();k++)
584 gezelter 3057 {
585 tim 2440 ang = fabs(vic[k]->_ang);
586     if (ang > 5.0 && ang < 175.0)
587 gezelter 3057 continue;
588 tim 2440 atom = mol.GetAtom(k);
589     done = false;
590     for (a = mol.BeginAtom(i);a && a->GetIdx() < k && !done;a = mol.NextAtom(i))
591 gezelter 3057 for (b=mol.BeginAtom(j);b && b->GetIdx()<a->GetIdx() && !done;b = mol.NextAtom(j))
592 tim 2440 {
593 gezelter 3057 v1 = atom->GetVector() - a->GetVector();
594     v2 = b->GetVector() - a->GetVector();
595     ang = fabs(vectorAngle(v1,v2));
596     if (ang < 5.0 || ang > 175.0)
597     continue;
598 tim 2440
599 gezelter 3057 for (c = mol.BeginAtom(m);c && c->GetIdx() < atom->GetIdx();c = mol.NextAtom(m))
600     if (c != atom && c != a && c != b)
601     break;
602     if (!c)
603     continue;
604 tim 2440
605 gezelter 3057 vic[k]->_a = a;
606     vic[k]->_b = b;
607     vic[k]->_c = c;
608     vic[k]->_dst = v1.length();
609     vic[k]->_ang = vectorAngle(v1,v2);
610     vic[k]->_tor = CalcTorsionAngle(atom->GetVector(),
611     a->GetVector(),
612     b->GetVector(),
613     c->GetVector());
614     done = true;
615 tim 2440 }
616 gezelter 3057 }
617     }
618 tim 2440
619 gezelter 3057 OBAPI void qtrfit (double *r,double *f,int size, double u[3][3])
620     {
621 tim 2440 register int i;
622     double xxyx, xxyy, xxyz;
623     double xyyx, xyyy, xyyz;
624     double xzyx, xzyy, xzyz;
625     double d[4],q[4];
626     double c[16],v[16];
627     double rx,ry,rz,fx,fy,fz;
628    
629     /* generate the upper triangle of the quadratic form matrix */
630    
631     xxyx = 0.0;
632     xxyy = 0.0;
633     xxyz = 0.0;
634     xyyx = 0.0;
635     xyyy = 0.0;
636     xyyz = 0.0;
637     xzyx = 0.0;
638     xzyy = 0.0;
639     xzyz = 0.0;
640    
641     for (i = 0; i < size; i++)
642 gezelter 3057 {
643 tim 2440 rx = r[i*3];
644     ry = r[i*3+1];
645     rz = r[i*3+2];
646     fx = f[i*3];
647     fy = f[i*3+1];
648     fz = f[i*3+2];
649    
650     xxyx += fx * rx;
651     xxyy += fx * ry;
652     xxyz += fx * rz;
653     xyyx += fy * rx;
654     xyyy += fy * ry;
655     xyyz += fy * rz;
656     xzyx += fz * rx;
657     xzyy += fz * ry;
658     xzyz += fz * rz;
659 gezelter 3057 }
660 tim 2440
661     c[4*0+0] = xxyx + xyyy + xzyz;
662    
663     c[4*0+1] = xzyy - xyyz;
664     c[4*1+1] = xxyx - xyyy - xzyz;
665    
666     c[4*0+2] = xxyz - xzyx;
667     c[4*1+2] = xxyy + xyyx;
668     c[4*2+2] = xyyy - xzyz - xxyx;
669    
670     c[4*0+3] = xyyx - xxyy;
671     c[4*1+3] = xzyx + xxyz;
672     c[4*2+3] = xyyz + xzyy;
673     c[4*3+3] = xzyz - xxyx - xyyy;
674    
675     /* diagonalize c */
676    
677     matrix3x3::jacobi(4, c, d, v);
678    
679     /* extract the desired quaternion */
680    
681     q[0] = v[4*0+3];
682     q[1] = v[4*1+3];
683     q[2] = v[4*2+3];
684     q[3] = v[4*3+3];
685    
686     /* generate the rotation matrix */
687    
688     u[0][0] = q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3];
689     u[1][0] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
690     u[2][0] = 2.0 * (q[1] * q[3] + q[0] * q[2]);
691    
692     u[0][1] = 2.0 * (q[2] * q[1] + q[0] * q[3]);
693     u[1][1] = q[0]*q[0] - q[1]*q[1] + q[2]*q[2] - q[3]*q[3];
694     u[2][1] = 2.0 * (q[2] * q[3] - q[0] * q[1]);
695    
696     u[0][2] = 2.0 * (q[3] * q[1] - q[0] * q[2]);
697     u[1][2] = 2.0 * (q[3] * q[2] + q[0] * q[1]);
698     u[2][2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
699 gezelter 3057 }
700 tim 2440
701    
702    
703 gezelter 3057 static double Roots[4];
704 tim 2440
705     #define ApproxZero 1E-7
706     #define IsZero(x) ((double)fabs(x)<ApproxZero)
707     #ifndef PI
708     #define PI 3.14159265358979323846226433
709     #endif
710     #define OneThird (1.0/3.0)
711     #define FourThirdsPI (4.0*PI/3.0)
712     #define TwoThirdsPI (2.0*PI/3.0)
713    
714     #ifdef OLD_RMAT
715    
716 gezelter 3057 /*FUNCTION */
717     /* recieves: the co-efficients for a general
718     * equation of degree one.
719     * Ax + B = 0 !!
720     */
721     OBAPI static int SolveLinear(double A,double B)
722     {
723 tim 2440 if( IsZero(A) )
724 gezelter 3057 return( 0 );
725 tim 2440 Roots[0] = -B/A;
726     return( 1 );
727 gezelter 3057 }
728 tim 2440
729 gezelter 3057 /*FUNCTION */
730     /* recieves: the co-efficients for a general
731     * linear equation of degree two.
732     * Ax^2 + Bx + C = 0 !!
733     */
734     OBAPI static int SolveQuadratic(double A,double B,double C)
735     {
736 tim 2440 register double Descr, Temp, TwoA;
737    
738     if( IsZero(A) )
739 gezelter 3057 return( SolveLinear(B,C) );
740 tim 2440
741     TwoA = A+A;
742     Temp = TwoA*C;
743     Descr = B*B - (Temp+Temp);
744     if( Descr<0.0 )
745 gezelter 3057 return( 0 );
746 tim 2440
747     if( Descr>0.0 )
748 gezelter 3057 {
749 tim 2440 Descr = sqrt(Descr);
750     #ifdef ORIG
751    
752     Roots[0] = (-B-Descr)/TwoA;
753     Roots[1] = (-B+Descr)/TwoA;
754     #else
755     /* W. Press, B. Flannery, S. Teukolsky and W. Vetterling,
756 gezelter 3057 * "Quadratic and Cubic Equations", Numerical Recipes in C,
757     * Chapter 5, pp. 156-157, 1989.
758     */
759 tim 2440 Temp = (B<0.0)? -0.5*(B-Descr) : -0.5*(B+Descr);
760     Roots[0] = Temp/A;
761     Roots[1] = C/Temp;
762     #endif
763    
764     return( 2 );
765 gezelter 3057 }
766 tim 2440 Roots[0] = -B/TwoA;
767     return( 1 );
768 gezelter 3057 }
769 tim 2440
770 gezelter 3057 /*FUNCTION */
771     /* task: to return the cube root of the
772     * given value taking into account
773     * that it may be negative.
774     */
775     OBAPI static double CubeRoot(double X)
776     {
777 tim 2440 if( X>=0.0 )
778 gezelter 3057 {
779 tim 2440 return pow( X, OneThird );
780 gezelter 3057 }
781 tim 2440 else
782 gezelter 3057 return -pow( -X, OneThird );
783     }
784 tim 2440
785 gezelter 3057 OBAPI static int SolveCubic(double A,double B,double C,double D)
786     {
787 tim 2440 register double TwoA, ThreeA, BOver3A;
788     register double Temp, POver3, QOver2;
789     register double Desc, Rho, Psi;
790    
791    
792     if( IsZero(A) )
793 gezelter 3057 {
794 tim 2440 return( SolveQuadratic(B,C,D) );
795 gezelter 3057 }
796 tim 2440
797     TwoA = A+A;
798     ThreeA = TwoA+A;
799     BOver3A = B/ThreeA;
800     QOver2 = ((TwoA*BOver3A*BOver3A-C)*BOver3A+D)/TwoA;
801     POver3 = (C-B*BOver3A)/ThreeA;
802    
803    
804     Rho = POver3*POver3*POver3;
805     Desc = QOver2*QOver2 + Rho;
806    
807     if( Desc<=0.0 )
808 gezelter 3057 {
809 tim 2440 Rho = sqrt( -Rho );
810     Psi = OneThird*acos(-QOver2/Rho);
811     Temp = CubeRoot( Rho );
812     Temp = Temp+Temp;
813    
814     Roots[0] = Temp*cos( Psi )-BOver3A;
815     Roots[1] = Temp*cos( Psi+TwoThirdsPI )-BOver3A;
816     Roots[2] = Temp*cos( Psi+FourThirdsPI )-BOver3A;
817     return( 3 );
818 gezelter 3057 }
819 tim 2440
820     if( Desc> 0.0 )
821 gezelter 3057 {
822 tim 2440 Temp = CubeRoot( -QOver2 );
823     Roots[0] = Temp+Temp-BOver3A;
824     Roots[1] = -Temp-BOver3A;
825     return( 2 );
826 gezelter 3057 }
827 tim 2440
828     Desc = sqrt( Desc );
829     Roots[0] = CubeRoot(Desc-QOver2)-CubeRoot(Desc+QOver2) - BOver3A;
830    
831     return( 1 );
832 gezelter 3057 }
833 tim 2440 #endif
834    
835    
836     #define MAX_SWEEPS 50
837    
838 gezelter 3057 OBAPI void ob_make_rmat(double a[3][3],double rmat[9])
839     {
840 tim 2440 double onorm, dnorm;
841     double b, dma, q, t, c, s,d[3];
842     double atemp, vtemp, dtemp,v[3][3];
843     double r1[3],r2[3],v1[3],v2[3],v3[3];
844     int i, j, k, l;
845    
846     memset((char*)d,'\0',sizeof(double)*3);
847    
848     for (j = 0; j < 3; j++)
849 gezelter 3057 {
850 tim 2440 for (i = 0; i < 3; i++)
851 gezelter 3057 v[i][j] = 0.0;
852 tim 2440
853     v[j][j] = 1.0;
854     d[j] = a[j][j];
855 gezelter 3057 }
856 tim 2440
857     for (l = 1; l <= MAX_SWEEPS; l++)
858 gezelter 3057 {
859 tim 2440 dnorm = 0.0;
860     onorm = 0.0;
861     for (j = 0; j < 3; j++)
862 gezelter 3057 {
863 tim 2440 dnorm = dnorm + (double)fabs(d[j]);
864     for (i = 0; i <= j - 1; i++)
865 gezelter 3057 {
866 tim 2440 onorm = onorm + (double)fabs(a[i][j]);
867 gezelter 3057 }
868     }
869 tim 2440
870     if((onorm/dnorm) <= 1.0e-12)
871 gezelter 3057 goto Exit_now;
872 tim 2440 for (j = 1; j < 3; j++)
873 gezelter 3057 {
874 tim 2440 for (i = 0; i <= j - 1; i++)
875 gezelter 3057 {
876 tim 2440 b = a[i][j];
877     if(fabs(b) > 0.0)
878 gezelter 3057 {
879 tim 2440 dma = d[j] - d[i];
880     if((fabs(dma) + fabs(b)) <= fabs(dma))
881 gezelter 3057 t = b / dma;
882 tim 2440 else
883 gezelter 3057 {
884 tim 2440 q = 0.5 * dma / b;
885     t = 1.0/((double)fabs(q) + (double)sqrt(1.0+q*q));
886     if(q < 0.0)
887 gezelter 3057 t = -t;
888     }
889 tim 2440 c = 1.0/(double)sqrt(t * t + 1.0);
890     s = t * c;
891     a[i][j] = 0.0;
892     for (k = 0; k <= i-1; k++)
893 gezelter 3057 {
894 tim 2440 atemp = c * a[k][i] - s * a[k][j];
895     a[k][j] = s * a[k][i] + c * a[k][j];
896     a[k][i] = atemp;
897 gezelter 3057 }
898 tim 2440 for (k = i+1; k <= j-1; k++)
899 gezelter 3057 {
900 tim 2440 atemp = c * a[i][k] - s * a[k][j];
901     a[k][j] = s * a[i][k] + c * a[k][j];
902     a[i][k] = atemp;
903 gezelter 3057 }
904 tim 2440 for (k = j+1; k < 3; k++)
905 gezelter 3057 {
906 tim 2440 atemp = c * a[i][k] - s * a[j][k];
907     a[j][k] = s * a[i][k] + c * a[j][k];
908     a[i][k] = atemp;
909 gezelter 3057 }
910 tim 2440 for (k = 0; k < 3; k++)
911 gezelter 3057 {
912 tim 2440 vtemp = c * v[k][i] - s * v[k][j];
913     v[k][j] = s * v[k][i] + c * v[k][j];
914     v[k][i] = vtemp;
915 gezelter 3057 }
916 tim 2440 dtemp = c*c*d[i] + s*s*d[j] - 2.0*c*s*b;
917     d[j] = s*s*d[i] + c*c*d[j] + 2.0*c*s*b;
918     d[i] = dtemp;
919 gezelter 3057 } /* end if */
920     } /* end for i */
921     } /* end for j */
922     } /* end for l */
923 tim 2440
924 gezelter 3057 Exit_now:
925 tim 2440
926     /* max_sweeps = l;*/
927    
928     for (j = 0; j < 3-1; j++)
929 gezelter 3057 {
930 tim 2440 k = j;
931     dtemp = d[k];
932     for (i = j+1; i < 3; i++)
933 gezelter 3057 if(d[i] < dtemp)
934 tim 2440 {
935 gezelter 3057 k = i;
936     dtemp = d[k];
937 tim 2440 }
938    
939     if(k > j)
940 gezelter 3057 {
941 tim 2440 d[k] = d[j];
942     d[j] = dtemp;
943     for (i = 0; i < 3 ; i++)
944 gezelter 3057 {
945 tim 2440 dtemp = v[i][k];
946     v[i][k] = v[i][j];
947     v[i][j] = dtemp;
948 gezelter 3057 }
949     }
950     }
951 tim 2440
952     r1[0] = v[0][0];
953     r1[1] = v[1][0];
954     r1[2] = v[2][0];
955     r2[0] = v[0][1];
956     r2[1] = v[1][1];
957     r2[2] = v[2][1];
958    
959     v3[0] = r1[1]*r2[2] - r1[2]*r2[1];
960     v3[1] = -r1[0]*r2[2] + r1[2]*r2[0];
961     v3[2] = r1[0]*r2[1] - r1[1]*r2[0];
962     s = (double)sqrt(v3[0]*v3[0] + v3[1]*v3[1] + v3[2]*v3[2]);
963     v3[0] /= s;
964     v3[0] /= s;
965     v3[0] /= s;
966    
967     v2[0] = v3[1]*r1[2] - v3[2]*r1[1];
968     v2[1] = -v3[0]*r1[2] + v3[2]*r1[0];
969     v2[2] = v3[0]*r1[1] - v3[1]*r1[0];
970     s = (double)sqrt(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]);
971     v2[0] /= s;
972     v2[0] /= s;
973     v2[0] /= s;
974    
975     v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
976     v1[1] = -v2[0]*v3[2] + v2[2]*v3[0];
977     v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
978     s = (double)sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
979     v1[0] /= s;
980     v1[0] /= s;
981     v1[0] /= s;
982    
983     rmat[0] = v1[0];
984     rmat[1] = v1[1];
985     rmat[2] = v1[2];
986     rmat[3] = v2[0];
987     rmat[4] = v2[1];
988     rmat[5] = v2[2];
989     rmat[6] = v3[0];
990     rmat[7] = v3[1];
991     rmat[8] = v3[2];
992 gezelter 3057 }
993 tim 2440
994 gezelter 3057 static int get_roots_3_3(double mat[3][3], double roots[3])
995     {
996 tim 2440 double rmat[9];
997    
998     ob_make_rmat(mat,rmat);
999    
1000     mat[0][0]=rmat[0];
1001     mat[0][1]=rmat[3];
1002     mat[0][2]=rmat[6];
1003     mat[1][0]=rmat[1];
1004     mat[1][1]=rmat[4];
1005     mat[1][2]=rmat[7];
1006     mat[2][0]=rmat[2];
1007     mat[2][1]=rmat[5];
1008     mat[2][2]=rmat[8];
1009    
1010     roots[0]=(double)Roots[0];
1011     roots[1]=(double)Roots[1];
1012     roots[2]=(double)Roots[2];
1013    
1014     return 1;
1015 gezelter 3057 }
1016 tim 2440
1017 gezelter 3057 OBAPI double superimpose(double *r,double *f,int size)
1018     {
1019 tim 2440 int i,j;
1020     double x,y,z,d2;
1021     double mat[3][3],rmat[3][3],mat2[3][3],roots[3];
1022    
1023     /* make inertial cross tensor */
1024     for(i=0;i<3;i++)
1025 gezelter 3057 for(j=0;j<3;j++)
1026     mat[i][j]=0.0;
1027 tim 2440
1028     for(i=0;i < size;i++)
1029 gezelter 3057 {
1030 tim 2440 mat[0][0]+=r[3*i] *f[3*i];
1031     mat[1][0]+=r[3*i+1]*f[3*i];
1032     mat[2][0]+=r[3*i+2]*f[3*i];
1033     mat[0][1]+=r[3*i] *f[3*i+1];
1034     mat[1][1]+=r[3*i+1]*f[3*i+1];
1035     mat[2][1]+=r[3*i+2]*f[3*i+1];
1036     mat[0][2]+=r[3*i] *f[3*i+2];
1037     mat[1][2]+=r[3*i+1]*f[3*i+2];
1038     mat[2][2]+=r[3*i+2]*f[3*i+2];
1039 gezelter 3057 }
1040 tim 2440
1041     d2=mat[0][0]*(mat[1][1]*mat[2][2]-mat[1][2]*mat[2][1])
1042 gezelter 3057 -mat[0][1]*(mat[1][0]*mat[2][2]-mat[1][2]*mat[2][0])
1043     +mat[0][2]*(mat[1][0]*mat[2][1]-mat[1][1]*mat[2][0]);
1044 tim 2440
1045    
1046     /* square matrix= ((mat transpose) * mat) */
1047     for(i=0;i<3;i++)
1048 gezelter 3057 for(j=0;j<3;j++)
1049 tim 2440 {
1050 gezelter 3057 x=mat[0][i]*mat[0][j]+mat[1][i]*mat[1][j]+mat[2][i]*mat[2][j];
1051     mat2[i][j]=mat[i][j];
1052     rmat[i][j]=x;
1053 tim 2440 }
1054     get_roots_3_3(rmat,roots);
1055    
1056     roots[0]=(roots[0]<0.0001) ? 0.0: (roots[0]);
1057     roots[1]=(roots[1]<0.0001) ? 0.0: (roots[1]);
1058     roots[2]=(roots[2]<0.0001) ? 0.0: (roots[2]);
1059    
1060     /* make sqrt of rmat, store in mat*/
1061    
1062     roots[0]=roots[0]<0.0001? 0.0: 1.0/(double)sqrt(roots[0]);
1063     roots[1]=roots[1]<0.0001? 0.0: 1.0/(double)sqrt(roots[1]);
1064     roots[2]=roots[2]<0.0001? 0.0: 1.0/(double)sqrt(roots[2]);
1065    
1066     if(d2<0.0)
1067 gezelter 3057 {
1068 tim 2440 if( (roots[0]>=roots[1]) && (roots[0]>=roots[2]) )
1069 gezelter 3057 roots[0]*=-1.0;
1070 tim 2440 if( (roots[1]>roots[0]) && (roots[1]>=roots[2]) )
1071 gezelter 3057 roots[1]*=-1.0;
1072 tim 2440 if( (roots[2]>roots[1]) && (roots[2]>roots[0]) )
1073 gezelter 3057 roots[2]*=-1.0;
1074     }
1075 tim 2440
1076     for(i=0;i<3;i++)
1077 gezelter 3057 for(j=0;j<3;j++)
1078     mat[i][j]=roots[0]*rmat[i][0]*rmat[j][0]+
1079     roots[1]*rmat[i][1]*rmat[j][1]+
1080     roots[2]*rmat[i][2]*rmat[j][2];
1081 tim 2440
1082     /* and multiply into original inertial cross matrix, mat2 */
1083     for(i=0;i<3;i++)
1084 gezelter 3057 for(j=0;j<3;j++)
1085     rmat[i][j]=mat[0][j]*mat2[i][0]+
1086     mat[1][j]*mat2[i][1]+
1087     mat[2][j]*mat2[i][2];
1088 tim 2440
1089     /* rotate all coordinates */
1090     d2 = 0.0;
1091     for(i=0;i<size;i++)
1092 gezelter 3057 {
1093 tim 2440 x=f[3*i]*rmat[0][0]+f[3*i+1]*rmat[0][1]+f[3*i+2]*rmat[0][2];
1094     y=f[3*i]*rmat[1][0]+f[3*i+1]*rmat[1][1]+f[3*i+2]*rmat[1][2];
1095     z=f[3*i]*rmat[2][0]+f[3*i+1]*rmat[2][1]+f[3*i+2]*rmat[2][2];
1096     f[3*i ]=x;
1097     f[3*i+1]=y;
1098     f[3*i+2]=z;
1099    
1100     x = r[i*3] - f[i*3];
1101     y = r[i*3+1] - f[i*3+1];
1102     z = r[i*3+2] - f[i*3+2];
1103     d2 += x*x+y*y+z*z;
1104 gezelter 3057 }
1105 tim 2440
1106     d2 /= (double) size;
1107    
1108     return((double)sqrt(d2));
1109 gezelter 3057 }
1110 tim 2440
1111 gezelter 3057 OBAPI void get_rmat(double *rvec,double *r,double *f,int size)
1112     {
1113 tim 2440 int i,j;
1114     double x,d2;
1115     double mat[3][3],rmat[3][3],mat2[3][3],roots[3];
1116    
1117     /* make inertial cross tensor */
1118     for(i=0;i<3;i++)
1119 gezelter 3057 for(j=0;j<3;j++)
1120     mat[i][j]=0.0;
1121 tim 2440
1122     for(i=0;i < size;i++)
1123 gezelter 3057 {
1124 tim 2440 mat[0][0]+=r[3*i] *f[3*i];
1125     mat[1][0]+=r[3*i+1]*f[3*i];
1126     mat[2][0]+=r[3*i+2]*f[3*i];
1127     mat[0][1]+=r[3*i] *f[3*i+1];
1128     mat[1][1]+=r[3*i+1]*f[3*i+1];
1129     mat[2][1]+=r[3*i+2]*f[3*i+1];
1130     mat[0][2]+=r[3*i] *f[3*i+2];
1131     mat[1][2]+=r[3*i+1]*f[3*i+2];
1132     mat[2][2]+=r[3*i+2]*f[3*i+2];
1133 gezelter 3057 }
1134 tim 2440
1135     d2=mat[0][0]*(mat[1][1]*mat[2][2]-mat[1][2]*mat[2][1])
1136 gezelter 3057 -mat[0][1]*(mat[1][0]*mat[2][2]-mat[1][2]*mat[2][0])
1137     +mat[0][2]*(mat[1][0]*mat[2][1]-mat[1][1]*mat[2][0]);
1138 tim 2440
1139     /* square matrix= ((mat transpose) * mat) */
1140     for(i=0;i<3;i++)
1141 gezelter 3057 for(j=0;j<3;j++)
1142 tim 2440 {
1143 gezelter 3057 x=mat[0][i]*mat[0][j]+mat[1][i]*mat[1][j]+mat[2][i]*mat[2][j];
1144     mat2[i][j]=mat[i][j];
1145     rmat[i][j]=x;
1146 tim 2440 }
1147     get_roots_3_3(rmat,roots);
1148    
1149     roots[0]=(roots[0]<0.0001) ? 0.0: (roots[0]);
1150     roots[1]=(roots[1]<0.0001) ? 0.0: (roots[1]);
1151     roots[2]=(roots[2]<0.0001) ? 0.0: (roots[2]);
1152    
1153     /* make sqrt of rmat, store in mat*/
1154    
1155     roots[0]=(roots[0]<0.0001) ? 0.0: 1.0/(double)sqrt(roots[0]);
1156     roots[1]=(roots[1]<0.0001) ? 0.0: 1.0/(double)sqrt(roots[1]);
1157     roots[2]=(roots[2]<0.0001) ? 0.0: 1.0/(double)sqrt(roots[2]);
1158    
1159     if(d2<0.0)
1160 gezelter 3057 {
1161 tim 2440 if( (roots[0]>=roots[1]) && (roots[0]>=roots[2]) )
1162 gezelter 3057 roots[0]*=-1.0;
1163 tim 2440 if( (roots[1]>roots[0]) && (roots[1]>=roots[2]) )
1164 gezelter 3057 roots[1]*=-1.0;
1165 tim 2440 if( (roots[2]>roots[1]) && (roots[2]>roots[0]) )
1166 gezelter 3057 roots[2]*=-1.0;
1167     }
1168 tim 2440
1169     for(i=0;i<3;i++)
1170 gezelter 3057 for(j=0;j<3;j++)
1171     mat[i][j]=roots[0]*rmat[i][0]*rmat[j][0]+
1172     roots[1]*rmat[i][1]*rmat[j][1]+
1173     roots[2]*rmat[i][2]*rmat[j][2];
1174 tim 2440
1175     /* and multiply into original inertial cross matrix, mat2 */
1176     for(i=0;i<3;i++)
1177 gezelter 3057 for(j=0;j<3;j++)
1178     rmat[i][j]=mat[0][j]*mat2[i][0]+
1179     mat[1][j]*mat2[i][1]+
1180     mat[2][j]*mat2[i][2];
1181 tim 2440
1182     rvec[0] = rmat[0][0];
1183     rvec[1] = rmat[0][1];
1184     rvec[2] = rmat[0][2];
1185     rvec[3] = rmat[1][0];
1186     rvec[4] = rmat[1][1];
1187     rvec[5] = rmat[1][2];
1188     rvec[6] = rmat[2][0];
1189     rvec[7] = rmat[2][1];
1190     rvec[8] = rmat[2][2];
1191 gezelter 3057 }
1192 tim 2440
1193     } // end namespace OpenBabel
1194    
1195     //! \file obutil.cpp
1196     //! \brief Various utility methods.