glsimplemoleculeview.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                   glsimplemoleculeview.cpp  -  description
00003                              -------------------
00004     begin                : Fri Nov 5 2004
00005     copyright            : (C) 2004-2006 by Ben Swerts
00006     email                : bswerts@users.sourceforge.net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00019 
00027 
00028 
00029 
00031 
00032 // C++ header files
00033 #include <cassert>
00034 #include <cmath>
00035 
00036 // STL header files
00037 #include <algorithm>
00038 
00039 // Qt header files
00040 #include <qapplication.h>
00041 #include <qdom.h>
00042 #include <qfiledialog.h>
00043 #include <qmessagebox.h>
00044 #include <qpoint.h>
00045 #include <qstringlist.h>
00046 
00047 // Xbrabo header files
00048 #include "atomset.h"
00049 #include "domutils.h"
00050 #include "glsimplemoleculeview.h"
00051 #include "point3d.h"
00052 #include "vector3d.h"
00053 
00057 
00059 GLSimpleMoleculeView::GLSimpleMoleculeView(AtomSet* atomset, QWidget* parent, const char* name ) : GLView(parent, name),
00060   chargeType(AtomSet::None),
00061   atoms(atomset),
00062   scaleFactor(1.0f)
00064 {
00065   moleculeStyle = moleculeParameters.defaultMoleculeStyle;
00066   forcesStyle = moleculeParameters.defaultForcesStyle;
00067   showElements = moleculeParameters.showElements;
00068   showNumbers = moleculeParameters.showNumbers;
00069   assert(atomset != 0);
00070   centerMolecule(); // just sets centerX|Y|Z to zero when no atoms are present
00071   reorderShapes();
00072   labelFont = QApplication::font();
00073 #ifndef WIN32
00074   // Linux needs a non TTF font like Times (safest option)
00075   //labelFont = QFont("Times");
00076   // less safe option (not very well tested): use a bitmap font (works with MESA GL)
00077   labelFont.setStyleHint(QFont::AnyStyle, QFont::PreferBitmap); // uses a bitmap font
00078   labelFont.setPointSize(QApplication::font().pointSize());
00079   //labelFont.setStyleStrategy(QFont::OpenGLCompatible); // doesn't work on SuSE 9.2 64bit thru Cygwin/X and not supported on Qt 3.1.2
00080 #endif
00081 }
00082 
00084 GLSimpleMoleculeView::~GLSimpleMoleculeView()
00086 {
00087   makeCurrent();
00088   glDeleteLists(atomObject, 4);
00089 }
00090 
00092 unsigned int GLSimpleMoleculeView::displayStyle(const DisplaySource source) const
00094 {
00095   if(source == Molecule)
00096     return moleculeStyle;
00097   else
00098     return forcesStyle;
00099 }
00100 
00102 bool GLSimpleMoleculeView::isShowingElements() const
00104 {
00105   return showElements;
00106 }
00107 
00109 bool GLSimpleMoleculeView::isShowingNumbers() const
00111 {
00112   return showNumbers;
00113 }
00114 
00116 bool GLSimpleMoleculeView::isShowingCharges(const unsigned int type) const
00118 {
00119   return type == chargeType;
00120 }
00121 
00123 unsigned int GLSimpleMoleculeView::selectedAtoms() const
00125 {
00126   return selectionList.size();
00127 }
00129 void GLSimpleMoleculeView::loadCML(QDomElement* root)
00131 {
00132   float wQuat = 0.0f, xQuat = 0.0f, yQuat = 0.0f, zQuat = 0.0f;
00133   QDomNode childNode = root->firstChild();
00134   const QString prefix = "view_";
00135   while(!childNode.isNull())
00136   {
00137     if(childNode.isElement() && childNode.nodeName() == "parameter")
00138     {
00139       if(DomUtils::dictEntry(childNode, prefix + "orientation-w"))
00140         DomUtils::readNode(&childNode, &wQuat);
00141       else if(DomUtils::dictEntry(childNode, prefix + "orientation-x"))
00142         DomUtils::readNode(&childNode, &xQuat);
00143       else if(DomUtils::dictEntry(childNode, prefix + "orientation-y"))
00144         DomUtils::readNode(&childNode, &yQuat);
00145       else if(DomUtils::dictEntry(childNode, prefix + "orientation-z"))
00146         DomUtils::readNode(&childNode, &zQuat);
00147       else if(DomUtils::dictEntry(childNode, prefix + "position-x"))
00148         DomUtils::readNode(&childNode, &xPos);
00149       else if(DomUtils::dictEntry(childNode, prefix + "position-y"))
00150         DomUtils::readNode(&childNode, &yPos);
00151       else if(DomUtils::dictEntry(childNode, prefix + "position-z"))
00152         DomUtils::readNode(&childNode, &zPos);
00153       else if(DomUtils::dictEntry(childNode, prefix + "center-x"))
00154         DomUtils::readNode(&childNode, &centerX);
00155       else if(DomUtils::dictEntry(childNode, prefix + "center-y"))
00156         DomUtils::readNode(&childNode, &centerY);
00157       else if(DomUtils::dictEntry(childNode, prefix + "center-z"))
00158         DomUtils::readNode(&childNode, &centerZ);
00159       else if(DomUtils::dictEntry(childNode, prefix + "style_molecule"))
00160         DomUtils::readNode(&childNode, &moleculeStyle);
00161       else if(DomUtils::dictEntry(childNode, prefix + "style_forces"))
00162         DomUtils::readNode(&childNode, &forcesStyle);
00163       else if(DomUtils::dictEntry(childNode, prefix + "show_elements"))
00164         DomUtils::readNode(&childNode, &showElements);
00165       else if(DomUtils::dictEntry(childNode, prefix + "show_numbers"))
00166         DomUtils::readNode(&childNode, &showNumbers);
00167       else if(DomUtils::dictEntry(childNode, prefix + "show_charges_type"))
00168         DomUtils::readNode(&childNode, &chargeType);
00169     }
00170     childNode = childNode.nextSibling();
00171   }
00172   orientationQuaternion->setValues(wQuat, xQuat, yQuat, zQuat);
00173 
00174   makeCurrent(); // needed for call to updateFog
00175   updateFog(boundingSphereRadius());
00176   updateGL();
00177 }
00178 
00180 void GLSimpleMoleculeView::saveCML(QDomElement* root)
00182 {
00183   const QString prefix = "view_";
00184   DomUtils::makeNode(root, orientationQuaternion->w(), prefix + "orientation-w");
00185   DomUtils::makeNode(root, orientationQuaternion->x(), prefix + "orientation-x");
00186   DomUtils::makeNode(root, orientationQuaternion->y(), prefix + "orientation-y");
00187   DomUtils::makeNode(root, orientationQuaternion->z(), prefix + "orientation-z");
00188   DomUtils::makeNode(root, static_cast<float>(xPos), prefix + "position-x");
00189   DomUtils::makeNode(root, static_cast<float>(yPos), prefix + "position-y");
00190   DomUtils::makeNode(root, static_cast<float>(zPos), prefix + "position-z");
00191   DomUtils::makeNode(root, static_cast<float>(centerX), prefix + "center-x");
00192   DomUtils::makeNode(root, static_cast<float>(centerY), prefix + "center-y");
00193   DomUtils::makeNode(root, static_cast<float>(centerZ), prefix + "center-z");
00194   DomUtils::makeNode(root, moleculeStyle, prefix + "style_molecule");
00195   DomUtils::makeNode(root, forcesStyle, prefix + "style_forces");
00196   DomUtils::makeNode(root, showElements, prefix + "show_elements");
00197   DomUtils::makeNode(root, showNumbers, prefix + "show_numbers");
00198   DomUtils::makeNode(root, chargeType, prefix + "show_charges_type");
00199 }
00200 
00202 void GLSimpleMoleculeView::setDisplayStyle(const DisplaySource source, const unsigned int style)
00204 {
00205   if(source == Molecule)
00206   {
00207     if(style > VanDerWaals)
00208       moleculeStyle = BallAndStick;
00209     else
00210       moleculeStyle = style;
00211   }
00212   else
00213   {
00214     if(style > Tubes)
00215       forcesStyle = Tubes;
00216     else
00217       forcesStyle = style;
00218   }
00219   setModified();
00220 }
00221 
00223 void GLSimpleMoleculeView::setLabels(const bool element, const bool number, const unsigned int type)
00225 {
00226   showElements = element;
00227   showNumbers = number;
00228   if(type > AtomSet::Stockholder)
00229     chargeType = AtomSet::None;
00230   else
00231     chargeType = type;
00232   setModified();
00233 }
00234 
00236 void GLSimpleMoleculeView::setParameters(GLMoleculeParameters params)
00239 {
00240   moleculeParameters = params;
00241   //staticUpdateIndex++; //assume a call to GLView::setParameters has also been done
00242 }
00243 
00247 
00249 void GLSimpleMoleculeView::updateAtomSet(const bool reset)
00255 {
00256   centerMolecule(); // always keep the molecule centered
00257   if(reset)
00258   {
00259     resetView(false);
00260     unselectAll(false);
00261 
00262 
00263     /*qDebug("selecting all atoms 9+ Angstrom away from atom 16");
00264     unsigned int center = 15;
00265     double distance = 9.0;
00266     distance *= distance;
00267     for(unsigned int i = 0; i < atoms->count(); i++)
00268     {
00269       if(  (atoms->x(i) - atoms->x(center))*(atoms->x(i) - atoms->x(center))
00270          + (atoms->y(i) - atoms->y(center))*(atoms->y(i) - atoms->y(center))
00271          + (atoms->z(i) - atoms->z(center))*(atoms->z(i) - atoms->z(center)) >= distance)
00272         selectionList.push_back(i);
00273     }
00274     */
00275     /*qDebug("selecting first 32 atoms");
00276     if(atoms->count() >= 32)
00277     {
00278       for(unsigned int i = 0; i < 32; i++)
00279         selectionList.push_back(i);
00280     }
00281     */
00282     switch(selectionList.size())
00283     {
00284       case 0: selectionType = SELECTION_NONE;
00285               break;
00286       case 1: selectionType = SELECTION_ATOM;
00287               break;
00288       case 2: selectionType = SELECTION_BOND;
00289               break;
00290       case 3: selectionType = SELECTION_ANGLE;
00291               break;
00292       case 4: selectionType = SELECTION_TORSION;
00293               break;
00294       default: selectionType = SELECTION_GROUP;
00295     }
00296 
00297   }
00298   updateGL();
00299 }
00300 
00302 void GLSimpleMoleculeView::selectAll(const bool update)
00304 {
00305   unselectAll(false);
00306   for(unsigned int i = 0; i < atoms->count(); i++)
00307     selectionList.push_back(i);
00308   switch(selectionList.size())
00309   {
00310     case 0: selectionType = SELECTION_NONE;
00311             break;
00312     case 1: selectionType = SELECTION_ATOM;
00313             break;
00314     case 2: selectionType = SELECTION_BOND;
00315             break;
00316     case 3: selectionType = SELECTION_ANGLE;
00317             break;
00318     case 4: selectionType = SELECTION_TORSION;
00319             break;
00320     default: selectionType = SELECTION_GROUP;
00321   }
00322   if(update)
00323     updateGL();
00324   emit changed();
00325 }
00326 
00328 void GLSimpleMoleculeView::unselectAll(const bool update)
00330 {
00331   selectionList.clear();
00332   selectionType = SELECTION_NONE;
00333 
00334   if(update)
00335     updateGL();
00336   emit changed();
00337 }
00338 
00342 
00344 void GLSimpleMoleculeView::reorderShapes()
00346 {
00347   updateShapes();
00348   std::sort(shapes.begin(), shapes.end());
00349 }
00350 
00354 
00356 void GLSimpleMoleculeView::keyPressEvent(QKeyEvent* e)
00359 {
00360   if(e->state() & Qt::ControlButton && (e->key() == Qt::Key_Plus || e->key() == Qt::Key_1))
00361   {
00362     labelFont.setPointSize(labelFont.pointSize() + 1);
00363     qDebug("increasing font size by 1");
00364     updateGL();
00365   }
00366   else if(e->state() & Qt::ControlButton && (e->key() == Qt::Key_Minus || e->key() == Qt::Key_2))
00367   {
00368     labelFont.setPointSize(labelFont.pointSize() - 1);
00369     qDebug("decreasing font size by 1");
00370     updateGL();
00371   }
00372   else
00373     GLView::keyPressEvent(e);
00374 }
00375 
00377 void GLSimpleMoleculeView::initializeGL()
00379 {
00380   int numSlices = static_cast<int>(pow(2.0,static_cast<double>(moleculeParameters.quality)));
00381   atomObject = makeObjects(numSlices);
00382   bondObject = atomObject + 1;
00383   forceObjectLines = atomObject + 2;
00384   forceObjectTubes = atomObject + 3;
00385   updateGLSettings();
00386 
00387   GLView::initializeGL();
00388 }
00389 
00391 float GLSimpleMoleculeView::boundingSphereRadius()
00393 {
00394   float radius = 0.0;
00395   float x, y, z, tempradius;
00396   for(unsigned int i = 0; i < atoms->count(); i++)
00397   {
00398     x = static_cast<float>(atoms->x(i) - centerX);
00399     y = static_cast<float>(atoms->y(i) - centerY);
00400     z = static_cast<float>(atoms->z(i) - centerZ);
00402     tempradius = sqrt(x*x + y*y + z*z) + static_cast<float>(AtomSet::vanderWaals(atoms->atomicNumber(i)))/2.0f;
00403     if(tempradius > radius)
00404       radius = tempradius;
00405   }
00406   if(radius > 25.0f)
00407   {
00408     scaleFactor = 25.0f/radius;
00409     radius = 25.0f;
00410   }
00411   else
00412     scaleFactor = 1.0f;
00413   if(radius < 0.4f) // VdW(H)
00414     radius = 0.4f;
00415   return radius;
00416 }
00417 
00419 void GLSimpleMoleculeView::drawItem(const unsigned int)
00423 {
00424 
00425 }
00426 
00428 void GLSimpleMoleculeView::clicked(const QPoint& position)
00430 {
00431   selectEntity(position);
00432 }
00433 
00435 void GLSimpleMoleculeView::updateGLSettings()
00439 {
00440   GLView::updateGLSettings(); // update the settings of the base class
00441 
00444   //int numSlices = static_cast<int>(pow(2.0,static_cast<double>(moleculeParameters.quality)));
00445   changeObjects(atomObject, moleculeParameters.quality);
00446 
00449   //makeCurrent();
00450   GLfloat lwRange[] = {0.0f, 0.0f};
00451   glGetFloatv(GL_LINE_WIDTH_RANGE, lwRange);
00452   GLfloat psRange[] = {0.0f, 0.0f};
00453   glGetFloatv(GL_POINT_SIZE_RANGE, psRange);
00455   selectionLineWidth = moleculeParameters.sizeLines * 3.0f;
00456   if(selectionLineWidth < 3.0f)
00457     selectionLineWidth = 3.0f;
00458   if(selectionLineWidth > lwRange[1])
00459     selectionLineWidth = lwRange[1];
00461   selectionPointSize = moleculeParameters.sizeLines * 5.0f;
00462   if(selectionPointSize < 5.0f)
00463     selectionPointSize = 5.0f;
00464   if(selectionPointSize > psRange[1])
00465     selectionPointSize = psRange[1];
00466 
00468   glLineWidth(moleculeParameters.sizeLines);
00469 
00471   reorderShapes();
00472 }
00473 
00475 void GLSimpleMoleculeView::updateShapes()
00477 {
00478   shapes.clear();
00479   ShapeProperties prop;
00480 
00481   // atoms
00482   prop.id = 0; // not used
00483   prop.opacity = 100; // always
00484   prop.type = SHAPE_ATOMS;
00485   shapes.push_back(prop);
00486   // bonds
00487   prop.id = 0; // not used
00488   prop.opacity = 100; // always
00489   prop.type = SHAPE_BONDS;
00490   shapes.push_back(prop);
00491   // forces
00492   prop.id = 0; // not used
00493   prop.opacity = moleculeParameters.opacityForces;
00494   prop.type = SHAPE_FORCES;
00495   shapes.push_back(prop);
00496   // labels
00497   prop.id = 0; // not used
00498   prop.opacity = 100; // always
00499   prop.type = SHAPE_LABELS;
00500   shapes.push_back(prop);
00501   // IC value
00502   prop.id = 0;
00503   prop.opacity = 100;
00504   prop.type = SHAPE_IC;
00505   shapes.push_back(prop);
00506   // selection
00507   prop.id = 0; // not used
00508   prop.opacity = moleculeParameters.opacitySelections;
00509   prop.type = SHAPE_SELECTION;
00510   shapes.push_back(prop);
00511 }
00512 
00516 
00518 GLuint GLSimpleMoleculeView::makeObjects(const int numSlices)
00520 {
00521   GLuint startList = glGenLists(4);
00522   changeObjects(startList, numSlices);
00523   return startList;
00524 }
00525 
00527 void GLSimpleMoleculeView::changeObjects(const GLuint startList, const int numSlices)
00529 {
00530   GLUquadricObj* qobj;
00531   qobj = gluNewQuadric();
00533   //gluQuadricDrawStyle(qobj, GLU_POINT); // default = GLU_FILL
00534   gluQuadricNormals(qobj, GLU_SMOOTH);
00535   gluQuadricOrientation(qobj, GLU_OUTSIDE);
00536 
00538   glNewList(startList, GL_COMPILE);
00539     gluSphere(qobj, 1.0f, numSlices, numSlices);
00540   glEndList();
00541 
00543   glNewList(startList + 1, GL_COMPILE);
00544     gluCylinder(qobj, 1.0f, 1.0f, cylinderHeight, numSlices, 1);
00545   glEndList();
00546 
00548   glNewList(startList + 2, GL_COMPILE);
00549     glBegin(GL_LINES);
00550       //glColor3f(1.0f, 1.0f, 0.0f);
00551       glVertex3f(0.0f, 0.0f, 0.0f);
00552       glVertex3f(0.0f, 0.0f, cylinderHeight);
00553       //glColor3f(0.5f, 0.5f, 0.0f);
00554       glVertex3f(0.0f, 0.0f, cylinderHeight);
00555       glVertex3f(-0.1f, -0.1f, 0.9f * cylinderHeight);
00556       glVertex3f(0.0f, 0.0f, cylinderHeight);
00557       glVertex3f(0.1f, 0.1f, 0.9f * cylinderHeight);
00558     glEnd();
00559   glEndList();
00560 
00562   glNewList(startList + 3, GL_COMPILE);
00563     /*
00564     // draw the top in the atoms' color
00565     glTranslatef(0.0f, 0.0f, 0.9f*cylinderHeight);
00566     gluCylinder(qobj, 1.0f, 0.0f, 0.1f*cylinderHeight, numSlices, 1);
00567     gluQuadricOrientation(qobj, GLU_INSIDE);
00568     gluDisk(qobj, 0.0f, 1.0f, numSlices, 1);
00569     gluQuadricOrientation(qobj, GLU_OUTSIDE);
00570     // draw the rest in yellow
00571     qglColor(QColor(255, 255, 0));
00572     glTranslatef(0.0f, 0.0f, -0.9f*cylinderHeight);
00573     gluCylinder(qobj, 1.0f, 0.2f, 0.9f*cylinderHeight, numSlices, 1);
00574     */
00575     gluCylinder(qobj, 1.0f, 1.0f, cylinderHeight - 2.4f, numSlices, 1); // 2.4 = 2 * 1.2
00576     glTranslatef(0.0f, 0.0f, cylinderHeight - 2.4f);
00577     gluCylinder(qobj, 1.2f, 0.0f, 2.4f, numSlices, 1);
00578     gluQuadricOrientation(qobj, GLU_INSIDE);
00579     gluDisk(qobj, 0.0f, 1.2f, numSlices, 1);
00580   glEndList();
00581 
00582   gluDeleteQuadric(qobj);
00583 }
00584 
00586 void GLSimpleMoleculeView::selectEntity(const QPoint position)
00588 {
00589   makeCurrent();
00591   const unsigned int BUFFER_SIZE = 64;
00592   GLuint selectionBuffer[BUFFER_SIZE]; // selection buffer
00593   GLuint* pBuffer = selectionBuffer;
00594   GLint viewport[4]; // viewport
00595 
00597   glSelectBuffer(BUFFER_SIZE, pBuffer); // set up the selection buffer
00598   glGetIntegerv(GL_VIEWPORT, viewport); // get the viewport
00599   glMatrixMode(GL_PROJECTION); // set projection mode
00600   glPushMatrix(); // save the matrix
00601   glRenderMode(GL_SELECT); // set selection mode
00602   glLoadIdentity();
00603   GLint xPosition = position.x();
00604   GLint yPosition = viewport[3] - position.y();
00605   gluPickMatrix(xPosition, yPosition, 2, 2, viewport); // set up a viewport of 2 pixels wide around the mouse position
00606   setPerspective(); // calls gluPerspective or glOrtho depending on the prespective setting
00607   glMatrixMode(GL_MODELVIEW);
00608 
00609   if(moleculeStyle == None || moleculeStyle == Lines)
00610   {
00612     unsigned int oldStyle = moleculeStyle;
00613     moleculeStyle = Tubes;
00614     updateGL();
00615     moleculeStyle = oldStyle;
00616   }
00617   else
00618     updateGL(); // just draw the scene
00619 
00621   GLint hits = glRenderMode(GL_RENDER);
00622 
00624   glMatrixMode(GL_PROJECTION);
00625   glPopMatrix();
00626   glMatrixMode(GL_MODELVIEW);
00627 
00629   if(hits != 0)
00630   {
00631     pBuffer++; // GLuint count = *pBuffer++; // the number of names in the buffer
00632     pBuffer++; // GLuint minz = *pBuffer++; // minimum z-value of selection
00633     pBuffer++; // GLuint maxz = *pBuffer++; // maximum z-value of selection
00634     GLuint id = *pBuffer; // the id of the first selection
00635     //qDebug("Number of selections: %d", count);
00636     //qDebug("ID of first selection: %d", id);
00637     processSelection(id);
00638     updateGL();
00639   }
00640   emit changed();
00641 }
00642 
00644 void GLSimpleMoleculeView::processSelection(const unsigned int id)
00647 {
00648   switch(id)
00649   {
00650     case START_BONDS:  selectionList.clear();
00651                        selectionType = SELECTION_BONDS;
00652                        break;
00653     case START_FORCES: selectionList.clear();
00654                        selectionType = SELECTION_FORCES;
00655                        break;
00656     default: if(id >= START_ATOMS)
00657     {
00658       unsigned int selectedAtom = id - START_ATOMS;
00659 
00661       std::list<unsigned int>::iterator it = std::find(selectionList.begin(), selectionList.end(), selectedAtom);
00662       if(it == selectionList.end())
00663       {
00665         selectionList.push_back(selectedAtom);
00666       }
00667       else
00668       {
00670         selectionList.erase(it);
00671       }
00672 
00674       switch(selectionList.size())
00675       {
00676         case 0: selectionType = SELECTION_NONE;
00677                 break;
00678         case 1: selectionType = SELECTION_ATOM;
00679                 break;
00680         case 2: selectionType = SELECTION_BOND;
00681                 break;
00682         case 3: selectionType = SELECTION_ANGLE;
00683                 break;
00684         case 4: selectionType = SELECTION_TORSION;
00685                 break;
00686         default: selectionType = SELECTION_GROUP;
00687       }
00688     }
00689   }
00690 }
00691 
00693 void GLSimpleMoleculeView::centerMolecule()
00696 {
00697   centerX = 0.0f;
00698   centerY = 0.0f;
00699   centerZ = 0.0f;
00700 
00701   if(atoms->count() == 0)
00702     return;
00703 
00705   double maxx = atoms->x(0);
00706   double maxy = atoms->y(0);
00707   double maxz = atoms->z(0);
00708   double minx = maxx;
00709   double miny = maxy;
00710   double minz = maxz;
00711   for(unsigned int i = 1; i < atoms->count(); i++)
00712   {
00713     if(atoms->x(i) > maxx)
00714       maxx = atoms->x(i);
00715     else if(atoms->x(i) < minx)
00716       minx = atoms->x(i);
00717     if(atoms->y(i) > maxy)
00718       maxy = atoms->y(i);
00719     else if(atoms->y(i) < miny)
00720       miny = atoms->y(i);
00721     if(atoms->z(i) > maxz)
00722       maxz = atoms->z(i);
00723     else if(atoms->z(i) < minz)
00724       minz = atoms->z(i);
00725   }
00727   centerX = static_cast<GLfloat>((maxx + minx)/2.0);
00728   centerY = static_cast<GLfloat>((maxy + miny)/2.0);
00729   centerZ = static_cast<GLfloat>((maxz + minz)/2.0);
00730 }
00731 
00733 void GLSimpleMoleculeView::drawScene()
00739 {
00740   //qDebug("starting drawScene for atoms->count() = %d", atoms->count());
00741   if(scaleFactor < 1.0f)
00742     glScalef(scaleFactor, scaleFactor, scaleFactor);
00743 
00744   glTranslatef(-centerX, -centerY, -centerZ); // center the molecule
00745 
00746   glInitNames();
00747   glPushName(0);
00748 
00750   unsigned int oldMoleculeStyle = moleculeStyle;
00751   unsigned int oldForcesStyle = forcesStyle;
00752   bool oldShowElements = showElements;
00753   bool oldShowNumbers = showNumbers;
00754   unsigned int oldChargeType = chargeType;
00755   if(atoms->count() > moleculeParameters.fastRenderLimit)
00756   {
00757     moleculeStyle = Lines;
00758     forcesStyle = None;
00759     showElements = false;
00760     showNumbers = false;
00761     chargeType = AtomSet::None;
00762   }
00763 
00764   bool usedBlending = false;
00766   for(unsigned int i = 0; i < shapes.size(); i++)
00767   {
00769     if(!usedBlending && shapes[i].opacity < 100)
00770     {
00771       usedBlending = true;
00772       glEnable(GL_BLEND);
00773     }
00774     switch(shapes[i].type)
00775     {
00776       case SHAPE_ATOMS:
00777         drawAtoms();
00778         break;
00779       case SHAPE_BONDS:
00780         drawBonds();
00781         break;
00782       case SHAPE_FORCES:
00783         drawForces();
00784         break;
00785       case SHAPE_LABELS:
00786         drawLabels();
00787         break;
00788       case SHAPE_IC:
00789         drawICValue();
00790         break;
00791       case SHAPE_SELECTION:
00792         drawSelections();
00793         break;
00794       default:
00795         //qDebug("about to call drawItem(%d)",i);
00796         drawItem(i);
00797     }
00798   }
00799   if(usedBlending)
00800     glDisable(GL_BLEND);
00801 
00803   if(atoms->count() > moleculeParameters.fastRenderLimit)
00804   {
00805     moleculeStyle = oldMoleculeStyle;
00806     forcesStyle = oldForcesStyle;
00807     showElements = oldShowElements;
00808     showNumbers = oldShowNumbers;
00809     chargeType = oldChargeType;
00810   }
00811 }
00812 
00814 void GLSimpleMoleculeView::drawAtoms()
00816 {
00817   //qDebug("calling drawAtoms");
00818   if(moleculeStyle == None || moleculeStyle == Lines)
00819     return;
00820 
00821   for(unsigned int i = 0; i < atoms->count(); i++)
00822   {
00823     glPushMatrix(); // save the current matrix
00824     qglColor(atoms->color(i)); // set the color (works cos of glColorMaterial)
00825     glTranslatef(atoms->x(i), atoms->y(i), atoms->z(i)); // set the position
00826     if(moleculeStyle == Tubes)
00827     {
00828       glScalef(moleculeParameters.sizeBonds,
00829                moleculeParameters.sizeBonds,
00830                moleculeParameters.sizeBonds);
00831     }
00832     else if(moleculeStyle == BallAndStick)
00833     {
00834       glScalef(AtomSet::vanderWaals(atoms->atomicNumber(i))/2.0f,
00835                AtomSet::vanderWaals(atoms->atomicNumber(i))/2.0f,
00836                AtomSet::vanderWaals(atoms->atomicNumber(i))/2.0f);
00837     }
00838     else if(moleculeStyle == VanDerWaals)
00839     {
00840       glScalef(AtomSet::vanderWaals(atoms->atomicNumber(i))*1.5f,
00841                AtomSet::vanderWaals(atoms->atomicNumber(i))*1.5f,
00842                AtomSet::vanderWaals(atoms->atomicNumber(i))*1.5f);
00843     }
00844     glLoadName(START_ATOMS+i);
00845     glCallList(atomObject); // make the atom
00846     glPopMatrix(); // restore the matrix
00847   }
00848   glLoadName(START_BONDS); // just to make sure the following items do not get the same name as the last atom
00849 }
00850 
00852 void GLSimpleMoleculeView::drawBonds()
00856 {
00857   //qDebug("calling drawBonds");
00858   if(moleculeStyle == None || moleculeStyle == VanDerWaals)
00859     return;
00860 
00861   float distance, distanceXY, x1, x2, y1, y2, z1, z2, phi, theta;
00862   vector<unsigned int>* firstAtom;
00863   vector<unsigned int>* secondAtom;
00864   atoms->bonds(firstAtom, secondAtom); // assigns both pointers
00865 
00866   if(moleculeStyle == Lines)
00867   {
00868     glLineWidth(moleculeParameters.sizeLines);
00869     glDisable(GL_LIGHTING);
00870     glBegin(GL_LINES);
00871       for(unsigned int i = 0; i < firstAtom->size(); i++)
00872       {
00873         const unsigned int atom1 = firstAtom->operator[](i);
00874         const unsigned int atom2 = secondAtom->operator[](i);
00875         if(atoms->color(atom1) == atoms->color(atom2))
00876         {
00878           qglColor(atoms->color(atom1));
00879           glVertex3d(atoms->x(atom1), atoms->y(atom1), atoms->z(atom1));
00880           glVertex3d(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2));
00881         }
00882         else
00883         {
00885           const double midX = (atoms->x(atom1) + atoms->x(atom2))/2.0;
00886           const double midY = (atoms->y(atom1) + atoms->y(atom2))/2.0;
00887           const double midZ = (atoms->z(atom1) + atoms->z(atom2))/2.0;
00888           qglColor(atoms->color(atom1));
00889           glVertex3d(atoms->x(atom1), atoms->y(atom1), atoms->z(atom1));
00890           glVertex3d(midX, midY, midZ);
00891 
00892           qglColor(atoms->color(atom2));
00893           glVertex3d(midX, midY, midZ);
00894           glVertex3d(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2));
00895         }
00896       }
00897     glEnd();
00898     glEnable(GL_LIGHTING);
00899     return;
00900   }
00901 
00904   for(unsigned int i = 0; i < firstAtom->size(); i++)
00905   {
00907     const unsigned int atom1 = firstAtom->operator[](i);
00908     const unsigned int atom2 = secondAtom->operator[](i);
00909 
00910     x1 = static_cast<float>(atoms->x(atom1));
00911     x2 = static_cast<float>(atoms->x(atom2));
00912     y1 = static_cast<float>(atoms->y(atom1));
00913     y2 = static_cast<float>(atoms->y(atom2));
00914     z1 = static_cast<float>(atoms->z(atom1));
00915     z2 = static_cast<float>(atoms->z(atom2));
00916     distanceXY = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
00917     distance = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
00918     if(distance < 0.01f)
00919       continue; //no need to draw those small bonds
00920 
00921     glPushMatrix();
00922 
00924     glTranslatef(x1, y1, z1);
00925 
00928     phi = acos((z2 - z1)/distance);
00930     if(distanceXY <= 0.0f)
00931       theta = 0.0f;
00932     else
00933     {
00934       theta = acos((x2 - x1)/distanceXY);
00935       if(y2 < y1)
00936         theta = 2.0f*Point3D<float>::PI - theta;
00937     }
00939     phi *= Point3D<float>::RADTODEG;
00940     theta *= Point3D<float>::RADTODEG;
00941     glRotatef(theta, 0.0f, 0.0f, 1.0f);
00942     glRotatef(phi, 0.0f, 1.0f, 0.0f);
00943 
00945     float scaleFactor = 1.0f;
00946     if(atoms->color(atom1) != atoms->color(atom2))
00947       scaleFactor = 2.0f;
00948     glScalef(moleculeParameters.sizeBonds, moleculeParameters.sizeBonds, distance/(scaleFactor*cylinderHeight));
00949 
00950     if(atoms->color(atom1) == atoms->color(atom2))
00951     {
00953       qglColor(atoms->color(atom1));
00954       glCallList(bondObject);
00955     }
00956     else
00957     {
00960       qglColor(atoms->color(atom1));
00961       glCallList(bondObject);
00963       qglColor(atoms->color(atom2));
00964       glTranslatef(0.0f, 0.0f, cylinderHeight);
00965       glCallList(bondObject);
00966     }
00967     glPopMatrix();
00968   }
00969 }
00970 
00972 void GLSimpleMoleculeView::drawLabels()
00974 {
00975   //qDebug("calling drawLabels");
00976   if(!(showElements || showNumbers || chargeType != AtomSet::None))
00977     return;
00978 
00979   // determine the amount of backrotation
00980   Vector3D<float> axis;
00981   float angle;
00982   orientationQuaternion->getAxisAngle(axis, angle);
00983 
00984   // set up the visuals
00985   glDisable(GL_LIGHTING);
00986   qglColor(moleculeParameters.colorLabels);
00987 
00988   // loop over the atoms
00989   for(unsigned int i = 0; i < atoms->count(); i++)
00990   {
00991     glPushMatrix();
00992     glTranslated(atoms->x(i), atoms->y(i), atoms->z(i));
00993     glRotatef(-angle, axis.x(), axis.y(), axis.z()); // backrotation
00994     QString label;
00995     if(showElements)
00996       label = AtomSet::numToAtom(atoms->atomicNumber(i)).stripWhiteSpace();
00997     if(showNumbers)
00998       label += QString::number(i + 1);
00999     if(chargeType != AtomSet::None)
01000     {
01001       if(showElements || showNumbers)
01002         label += "(";
01003 
01004       if(chargeType == AtomSet::Mulliken)
01005         label += QString::number(atoms->charge(AtomSet::Mulliken, i),'f',3);
01006       else
01007         label += QString::number(atoms->charge(AtomSet::Stockholder, i),'f',3);
01008 
01009       if(showElements || showNumbers)
01010         label += ")";
01011     }
01012     renderText(0.0, 0.0, AtomSet::vanderWaals(atoms->atomicNumber(i))/2.0 + 0.05, label, labelFont); // the +0.05 is needed for certain crappy Windows OpenGL drivers
01013     glPopMatrix();
01014   }
01015 
01016   // restore the lighting
01017   glEnable(GL_LIGHTING);
01018 }
01019 
01021 void GLSimpleMoleculeView::drawForces()
01025 {
01026   //qDebug("calling drawForces");
01027   if(forcesStyle == None || !atoms->hasForces())
01028     return;
01029 
01030   // forces are scaled. A force which is considered refined by relax (< 0.0009 mdyne/A) is equal
01031   // to 0.1 Angstrom.
01032   const float scaleFactor = 0.1f/0.0009f;
01033 
01034   const GLfloat opacity = moleculeParameters.opacityForces/100.0f;
01035   if(moleculeParameters.forcesOneColor)
01036   {
01037     // set the color and opacity here once
01038     const GLfloat red   = QColor(moleculeParameters.colorForces).red()/255.0f;
01039     const GLfloat green = QColor(moleculeParameters.colorForces).green()/255.0f;
01040     const GLfloat blue  = QColor(moleculeParameters.colorForces).blue()/255.0f;
01041     glColor4f(red, green, blue, opacity);
01042   }
01043 
01044   float x1, y1, z1, x2, y2, z2, distance, distanceXY, phi, theta;
01045   for(unsigned int i = 0; i < atoms->count(); i++)
01046   {
01047     x1 = static_cast<float>(atoms->x(i));
01048     y1 = static_cast<float>(atoms->y(i));
01049     z1 = static_cast<float>(atoms->z(i));
01050     x2 = static_cast<float>(atoms->dx(i));
01051     y2 = static_cast<float>(atoms->dy(i));
01052     z2 = static_cast<float>(atoms->dz(i));
01053     distanceXY = sqrt(x2*x2 + y2*y2);
01054     distance = sqrt(x2*x2 + y2*y2 + z2*z2);
01055     if(distance < 0.1f/scaleFactor)
01056       continue; //no need to draw those small (refined) forces
01057 
01058     glPushMatrix(); // save the current matrix
01059 
01061     glTranslatef(x1, y1, z1);
01064     phi = acos(z2/distance);
01066     if(distanceXY <= 0.01f)
01067       theta = 0.0f;
01068     else
01069     {
01070       theta = acos(x2/distanceXY);
01071       if(y2 < 0.0f)
01072         theta = 2.0f*Point3D<float>::PI - theta;
01073     }
01075     phi *= Point3D<float>::RADTODEG;
01076     theta *= Point3D<float>::RADTODEG;
01077     glRotatef(theta, 0.0f, 0.0f, 1.0f);
01078     glRotatef(phi, 0.0f, 1.0f, 0.0f);
01080     if(forcesStyle == Lines)
01081       glScalef(1.0f, 1.0f, scaleFactor*distance/(2.0f*cylinderHeight));
01082     else
01083       glScalef(moleculeParameters.sizeForces, moleculeParameters.sizeForces, scaleFactor*distance/(2.0f*cylinderHeight));
01084 
01085     if(!moleculeParameters.forcesOneColor)
01086     {
01087       const GLfloat red   = atoms->color(i).red()/255.0f;
01088       const GLfloat green = atoms->color(i).green()/255.0f;
01089       const GLfloat blue  = atoms->color(i).blue()/255.0f;
01090       glColor4f(red, green, blue, opacity);
01091     }
01092 
01093     //glLoadName(START_FORCES);
01094     if(forcesStyle == Lines)
01095       glCallList(forceObjectLines);
01096     else
01097       glCallList(forceObjectTubes);
01098 
01099     glPopMatrix(); // restore the matrix
01100   }
01101 }
01102 
01104 void GLSimpleMoleculeView::drawICValue()
01107 {
01108   //qDebug("calling drawICValue");
01110   glDisable(GL_LIGHTING);
01111   qglColor(moleculeParameters.colorICs);
01112 
01113   std::list<unsigned int>::iterator it = selectionList.begin();
01114   switch(selectionList.size())
01115   {
01116     case 2: 
01117     {
01118       // the atoms
01119       unsigned int atom1 = *it++;
01120       unsigned int atom2 = *it;
01121       float x1 = static_cast<float>(atoms->x(atom1));
01122       float x2 = static_cast<float>(atoms->x(atom2));
01123       float y1 = static_cast<float>(atoms->y(atom1));
01124       float y2 = static_cast<float>(atoms->y(atom2));
01125       float z1 = static_cast<float>(atoms->z(atom1));
01126       float z2 = static_cast<float>(atoms->z(atom2));
01127       // the text
01128       float distance = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
01129       // the actual rendering
01131       /*
01132       glPushMatrix();
01133       glTranslatef((x1 + x2)/2.0f, (y1 + y2)/2.0f, (z1 + z2)/2.0f);
01134       glRotatef(-angle, axis.x(), axis.y(), axis.z());
01135       renderText(0.0, 0.0, parameters.bondSizeBS + 0.01, QString::number(distance, 'f', 4), QFont("Times"));
01136       glPopMatrix();
01137       */
01139       // get the window coordinates of the centre of the bond
01140       GLdouble modelview[16];
01141       GLdouble projection[16];
01142       GLint viewport[4];
01143       glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01144       glGetDoublev(GL_PROJECTION_MATRIX, projection);
01145       glGetIntegerv(GL_VIEWPORT, viewport);
01146       GLdouble xwin, ywin, zwin;
01147       GLint result = gluProject((atoms->x(atom1)+atoms->x(atom2))/2.0, (atoms->y(atom1)+atoms->y(atom2))/2.0, (atoms->z(atom1)+atoms->z(atom2))/2.0, modelview, projection, viewport, &xwin, &ywin, &zwin);
01148       if(result == GL_FALSE)
01149         break;
01150       renderText(static_cast<int>(xwin), height() - static_cast<int>(ywin), QString::number(distance, 'f', 4), labelFont);
01151       break;
01152     }
01153     case 3: 
01154     {
01155       // the atoms
01156       unsigned int atom1 = *it++;
01157       unsigned int atom2 = *it++;
01158       unsigned int atom3 = *it;
01159       float x1 = static_cast<float>(atoms->x(atom1));
01160       float x2 = static_cast<float>(atoms->x(atom2));
01161       float x3 = static_cast<float>(atoms->x(atom3));
01162       float y1 = static_cast<float>(atoms->y(atom1));
01163       float y2 = static_cast<float>(atoms->y(atom2));
01164       float y3 = static_cast<float>(atoms->y(atom3));
01165       float z1 = static_cast<float>(atoms->z(atom1));
01166       float z2 = static_cast<float>(atoms->z(atom2));
01167       float z3 = static_cast<float>(atoms->z(atom3));
01168       // the text
01169       Vector3D<float> bond1(x2, y2, z2, x1, y1, z1);
01170       Vector3D<float> bond2(x2, y2, z2, x3, y3, z3);
01171       float localAngle = bond1.angle(bond2);
01172       // the actual rendering
01174       /*
01175       glPushMatrix();
01176       glTranslatef((x1 + x3)/2.0f, (y1 + y3)/2.0f, (z1 + z3)/2.0f);
01177       glRotatef(-angle, axis.x(), axis.y(), axis.z());
01178       renderText(0.0, 0.0, AtomSet::vanderWaals(atoms->atomicNumber(atom2))/2.0 + 0.01, QString::number(localAngle, 'f', 2), QFont("Times"));
01179       glPopMatrix();
01180       */
01182       GLdouble modelview[16];
01183       GLdouble projection[16];
01184       GLint viewport[4];
01185       glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01186       glGetDoublev(GL_PROJECTION_MATRIX, projection);
01187       glGetIntegerv(GL_VIEWPORT, viewport);
01188       GLdouble xwin, ywin, zwin;
01189       GLint result = gluProject((atoms->x(atom1)+atoms->x(atom3))/2.0, (atoms->y(atom1)+atoms->y(atom3))/2.0, (atoms->z(atom1)+atoms->z(atom3))/2.0, modelview, projection, viewport, &xwin, &ywin, &zwin);
01190       if(result == GL_FALSE)
01191         break;
01192       renderText(static_cast<int>(xwin), height() - static_cast<int>(ywin), QString::number(localAngle, 'f', 2), labelFont);
01193       break;
01194     }
01195     case 4: 
01196     {
01197       // the atoms
01198       unsigned int atom1 = *it++;
01199       unsigned int atom2 = *it++;
01200       unsigned int atom3 = *it++;
01201       unsigned int atom4 = *it;
01202       float x1 = static_cast<float>(atoms->x(atom1));
01203       float x2 = static_cast<float>(atoms->x(atom2));
01204       float x3 = static_cast<float>(atoms->x(atom3));
01205       float x4 = static_cast<float>(atoms->x(atom4));
01206       float y1 = static_cast<float>(atoms->y(atom1));
01207       float y2 = static_cast<float>(atoms->y(atom2));
01208       float y3 = static_cast<float>(atoms->y(atom3));
01209       float y4 = static_cast<float>(atoms->y(atom4));
01210       float z1 = static_cast<float>(atoms->z(atom1));
01211       float z2 = static_cast<float>(atoms->z(atom2));
01212       float z3 = static_cast<float>(atoms->z(atom3));
01213       float z4 = static_cast<float>(atoms->z(atom4));
01214       // the text
01215       Vector3D<float> bond1(x2, y2, z2, x1, y1, z1);
01216       Vector3D<float> bond2(x3, y3, z3, x4, y4, z4);
01217       Vector3D<float> centralbond(x2, y2, z2, x3, y3, z3);
01218       float localAngle = bond1.torsion(bond2, centralbond);
01219       // the actual rendering
01221       /*
01222       glPushMatrix();
01223       glTranslatef((x2 + x3)/2.0f, (y2 + y3)/2.0f, (z2 + z3)/2.0f);
01224       glRotatef(-angle, axis.x(), axis.y(), axis.z());
01225       renderText(0.0, 0.0, parameters.bondSizeBS + 0.01, QString::number(localAngle, 'f', 2), QFont("Times"));
01226       glPopMatrix();
01227       */
01229       GLdouble modelview[16];
01230       GLdouble projection[16];
01231       GLint viewport[4];
01232       glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01233       glGetDoublev(GL_PROJECTION_MATRIX, projection);
01234       glGetIntegerv(GL_VIEWPORT, viewport);
01235       GLdouble xwin, ywin, zwin;
01236       GLint result = gluProject((atoms->x(atom2)+atoms->x(atom3))/2.0, (atoms->y(atom2)+atoms->y(atom3))/2.0, (atoms->z(atom2)+atoms->z(atom3))/2.0, modelview, projection, viewport, &xwin, &ywin, &zwin);
01237       if(result == GL_FALSE)
01238         break;
01239       renderText(static_cast<int>(xwin), height() - static_cast<int>(ywin), QString::number(localAngle, 'f', 2), labelFont);
01240       break;
01241     }
01242   }
01243   glEnable(GL_LIGHTING);
01244 }
01245 
01247 void GLSimpleMoleculeView::drawSelections()
01249 {
01250   //qDebug("calling drawSelections");
01251   if(moleculeStyle == None || moleculeStyle == Lines)
01252   {
01253     qglColor(moleculeParameters.colorSelections);
01254     glDisable(GL_LIGHTING);
01256     glPointSize(selectionPointSize);
01257     glBegin(GL_POINTS);
01258       std::list<unsigned int>::iterator it = selectionList.begin();
01259       while(it != selectionList.end())
01260       {
01261         glVertex3d(atoms->x(*it), atoms->y(*it), atoms->z(*it));
01262         it++;
01263       }
01264     glEnd();
01266     if(selectionList.size() >= 2 && selectionList.size() <= 4)
01267     {
01268       glLineWidth(selectionLineWidth);
01270       std::list<unsigned int>::iterator it = selectionList.begin();
01271       glBegin(GL_LINE_STRIP);
01272         while(it != selectionList.end())
01273         {
01274           glVertex3d(atoms->x(*it), atoms->y(*it), atoms->z(*it));
01275           it++;
01276         }
01277       glEnd();
01278       glLineWidth(moleculeParameters.sizeLines);
01279     }
01280     glEnable(GL_LIGHTING);
01281     return;
01282   }
01283 
01284   const GLfloat red   = QColor(moleculeParameters.colorSelections).red()/255.0f;
01285   const GLfloat green = QColor(moleculeParameters.colorSelections).green()/255.0f;
01286   const GLfloat blue  = QColor(moleculeParameters.colorSelections).blue()/255.0f;
01287   const GLfloat opacity = moleculeParameters.opacitySelections/100.0f;
01288   glColor4f(red, green, blue, opacity);
01289 
01291   std::list<unsigned int>::iterator it = selectionList.begin();
01292   while(it != selectionList.end())
01293   {
01294     // draw a yellow halo around the selected atom
01295     glPushMatrix();
01296     glTranslatef(atoms->x(*it), atoms->y(*it), atoms->z(*it)); // set the position
01297     if(moleculeStyle == VanDerWaals)
01298     {
01299       glScalef(AtomSet::vanderWaals(atoms->atomicNumber(*it))*1.5f * 1.1f,
01300                AtomSet::vanderWaals(atoms->atomicNumber(*it))*1.5f * 1.1f,
01301                AtomSet::vanderWaals(atoms->atomicNumber(*it))*1.5f * 1.1f);
01302     }
01303     else if(moleculeStyle == Tubes)
01304     {
01305       glScalef(moleculeParameters.sizeBonds * 1.6f,
01306                moleculeParameters.sizeBonds * 1.6f,
01307                moleculeParameters.sizeBonds * 1.6f);
01308     }
01309     else
01310     {
01311       glScalef(AtomSet::vanderWaals(atoms->atomicNumber(*it))/2.0f * 1.1f,
01312                AtomSet::vanderWaals(atoms->atomicNumber(*it))/2.0f * 1.1f,
01313                AtomSet::vanderWaals(atoms->atomicNumber(*it))/2.0f * 1.1f);
01314     }
01315 
01316     glLoadName(START_SELECTEDATOMS);
01317     glCallList(atomObject); // make the atom
01318     glPopMatrix();
01319     it++;
01320   }
01321 
01323   if(selectionList.size() >= 2 && selectionList.size() <= 4)
01324   {
01325     float x1, y1, z1, x2, y2, z2, distance, distanceXY, phi, theta;
01326 
01327     std::list<unsigned int>::iterator it = selectionList.begin();
01328     unsigned int atom1 = *it++;
01329     unsigned int atom2 = *it;
01330     while(it != selectionList.end())
01331     {
01332       x1 = static_cast<float>(atoms->x(atom1));
01333       x2 = static_cast<float>(atoms->x(atom2));
01334       y1 = static_cast<float>(atoms->y(atom1));
01335       y2 = static_cast<float>(atoms->y(atom2));
01336       z1 = static_cast<float>(atoms->z(atom1));
01337       z2 = static_cast<float>(atoms->z(atom2));
01338       distanceXY = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
01339       distance = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
01340       if(distance < 0.01f)
01341         continue; //no need to draw those small bonds
01342 
01343       glPushMatrix();
01345       glTranslatef(x1, y1, z1);
01347       phi = acos((z2 - z1)/distance);
01348       if(distanceXY <= 0.0f)
01349         theta = 0.0f;
01350       else
01351       {
01352         theta = acos((x2 - x1)/distanceXY);
01353         if(y2 < y1)
01354           theta = 2.0f*Point3D<float>::PI - theta;
01355       }
01356       phi *= Point3D<float>::RADTODEG;
01357       theta *= Point3D<float>::RADTODEG;
01358       glRotatef(theta, 0.0f, 0.0f, 1.0f);
01359       glRotatef(phi, 0.0f, 1.0f, 0.0f);
01361       glScalef(moleculeParameters.sizeBonds * 1.1f, moleculeParameters.sizeBonds * 1.1f, distance/cylinderHeight);
01362       glLoadName(START_SELECTEDBONDS);
01363       glCallList(bondObject);
01364 
01365       glPopMatrix();
01366       atom1 = atom2;
01367       atom2 = *(++it);
01368     }
01369   }
01370 }
01371 
01375 
01376 const float GLSimpleMoleculeView::cylinderHeight = 10.0f;
01377 GLMoleculeParameters GLSimpleMoleculeView::moleculeParameters = {5, 1.0f, 0.2f, 0.2f, BallAndStick, Tubes, 1000, false, true,
01378 0x00FF00, 0x00FFFF, 0xFFFF00, 50, 0xFFFF0, false, 100};
01379 

Generated on Fri May 19 14:31:54 2006 for Brabosphere by  doxygen 1.4.6-NO