glmoleculeview.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                       glmoleculeview.cpp  -  description
00003                              -------------------
00004     begin                : Mon Jul 29 2002
00005     copyright            : (C) 2002-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 // STL header files
00033 #include <algorithm>
00034 
00035 // Qt header files
00036 #include <qfiledialog.h>
00037 #include <qinputdialog.h>
00038 #include <qmessagebox.h>
00039 //#include <qpoint.h>
00040 #include <qradiobutton.h>
00041 #include <qstringlist.h>
00042 #include <qtimer.h>
00043 #include <qvalidator.h>
00044 
00045 // Xbrabo header files
00046 #include "atomset.h"
00047 #include "coordinateswidget.h"
00048 #include "densitybase.h"
00049 #include "glmoleculeview.h"
00050 #include "isosurface.h"
00051 #include "newatombase.h"
00052 #include "point3d.h"
00053 #include "quaternion.h"
00054 #include "vector3d.h"
00055 
00059 
00061 GLMoleculeView::GLMoleculeView(AtomSet* atomset, QWidget* parent, const char* name) : GLSimpleMoleculeView(atomset, parent, name),
00062   atoms(atomset),
00063   densityDialog(NULL),
00064   newAtomDialog(NULL),
00065   manipulateSelection(false)
00067 {
00068   isoSurface = new IsoSurface();
00069 }
00070 
00072 GLMoleculeView::~GLMoleculeView()
00074 {
00075   makeCurrent();
00076   for(unsigned int i = 0; i < glSurfaces.size(); i++)
00077     glDeleteLists(glSurfaces[i], 1);
00078   delete isoSurface;
00079 }
00080 
00084 
00086 void GLMoleculeView::alterCartesian()
00090 {
00091   if(selectionList.size() == 0)
00092     return;
00093 
00095   CoordinatesWidget* coords = new CoordinatesWidget(this, 0, true);
00096   QDoubleValidator* v = new QDoubleValidator(-9999.0,9999.,12,this);
00097   coords->LineEditX->setValidator(v);
00098   coords->LineEditY->setValidator(v);
00099   coords->LineEditZ->setValidator(v);
00100   v = 0;
00101   if(selectionList.size() == 1)
00102   {
00103     // use default absolute changes
00104     unsigned int atom = *selectionList.begin();
00105     coords->LineEditX->setText(QString::number(atoms->x(atom), 'f', 8));
00106     coords->LineEditY->setText(QString::number(atoms->y(atom), 'f', 8));
00107     coords->LineEditZ->setText(QString::number(atoms->z(atom), 'f', 8));
00108   }
00109   else
00110   {
00111     // only relative changes
00112     coords->RadioButtonAbsolute->setEnabled(false);
00113     coords->RadioButtonRelative->setChecked(true);
00114     coords->LineEditX->setText("0.0");
00115     coords->LineEditY->setText("0.0");
00116     coords->LineEditZ->setText("0.0");
00117   }
00118 
00120   if(coords->exec() == QDialog::Accepted)
00121   {
00122     if(coords->RadioButtonAbsolute->isChecked())
00123     {
00124       // absolute changes for one atom
00125       unsigned int atom = *selectionList.begin();
00126       bool ok;
00127       double newx = coords->LineEditX->text().toDouble(&ok);
00128       if(ok)
00129         atoms->setX(atom, newx);
00130       double newy = coords->LineEditY->text().toDouble(&ok);
00131       if(ok)
00132         atoms->setY(atom, newy);
00133       double newz = coords->LineEditZ->text().toDouble(&ok);
00134       if(ok)
00135         atoms->setZ(atom, newz);
00136     }
00137     else
00138     {
00139       // relative changes for one or more atoms
00140       bool ok;
00141       double deltax = coords->LineEditX->text().toDouble(&ok);
00142       if(!ok)
00143         deltax = 0.0;
00144       double deltay = coords->LineEditY->text().toDouble(&ok);
00145       if(!ok)
00146         deltay = 0.0;
00147       double deltaz = coords->LineEditZ->text().toDouble(&ok);
00148       if(!ok)
00149         deltaz = 0.0;
00150       std::list<unsigned int>::iterator it = selectionList.begin();
00151       while(it != selectionList.end())
00152       {
00153         atoms->setX(*it, atoms->x(*it) + deltax);
00154         atoms->setY(*it, atoms->y(*it) + deltay);
00155         atoms->setZ(*it, atoms->z(*it) + deltaz);
00156         it++;
00157       }
00158     }
00159   }
00160   delete coords;
00161   setModified();
00162   updateAtomSet();
00163 }
00164 
00166 void GLMoleculeView::alterInternal()
00170 {
00171   switch(selectionType)
00172   {
00173     case SELECTION_BOND:
00174     {
00175       std::list<unsigned int>::iterator it = selectionList.begin();
00176       unsigned int atom1 = *it++;
00177       unsigned int atom2 = *it;
00179       // <double> version
00180       Vector3D<double> bond(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2), atoms->x(atom1), atoms->y(atom1), atoms->z(atom1));
00181       double bondLength = bond.length();
00182 
00183       bool ok;
00184       double newLength = QInputDialog::getDouble("Xbrabo", tr("Change the distance between atoms ")+QString::number(atom1+1)+" and "+QString::number(atom2+1), bondLength, -1000.0, 1000.0, 4, &ok, this);
00185       if(ok && fabs(newLength - bondLength) > 0.00001)
00186         atoms->changeBond(newLength - bondLength, atom1, atom2, true);
00187       else
00188         return; // no new value was entered
00189       break;
00190     }
00191 
00192     case SELECTION_ANGLE:
00193     {
00194       std::list<unsigned int>::iterator it = selectionList.begin();
00195       unsigned int atom1 = *it++;
00196       unsigned int atom2 = *it++;
00197       unsigned int atom3 = *it;
00199       Vector3D<double> bond1(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2), atoms->x(atom1), atoms->y(atom1), atoms->z(atom1));
00200       Vector3D<double> bond2(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2), atoms->x(atom3), atoms->y(atom3), atoms->z(atom3));
00201       double angle = bond1.angle(bond2);
00202       bool ok;
00203       double newAngle = QInputDialog::getDouble("Xbrabo", tr("Change the angle ")+QString::number(atom1+1)+"-"+QString::number(atom2+1)+"-"+QString::number(atom3+1), angle, -1000.0, 1000.0, 2, &ok, this);
00204       if(ok && fabs(newAngle - angle) > 0.001)
00205         atoms->changeAngle(newAngle - angle, atom1, atom2, atom3, true);
00206       else
00207         return; // no new value was entered
00208       break;
00209     }
00210 
00211     case SELECTION_TORSION:
00212     {
00213       std::list<unsigned int>::iterator it = selectionList.begin();
00214       unsigned int atom1 = *it++;
00215       unsigned int atom2 = *it++;
00216       unsigned int atom3 = *it++;
00217       unsigned int atom4 = *it;
00219       Vector3D<double> bond1(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2), atoms->x(atom1), atoms->y(atom1), atoms->z(atom1));
00220       Vector3D<double> centralbond(atoms->x(atom2), atoms->y(atom2), atoms->z(atom2), atoms->x(atom3), atoms->y(atom3), atoms->z(atom3));
00221       Vector3D<double> bond2(atoms->x(atom3), atoms->y(atom3), atoms->z(atom3), atoms->x(atom4), atoms->y(atom4), atoms->z(atom4));
00222       double torsion = bond1.torsion(bond2, centralbond);
00223       bool ok;
00224       double newTorsion = QInputDialog::getDouble("Xbrabo", tr("Change the torsion angle ")+QString::number(atom1+1)+"-"+QString::number(atom2+1)+"-"+QString::number(atom3+1)+"-"+QString::number(atom4+1), torsion, -1000.0, 1000.0, 2, &ok, this);
00225       if(ok && fabs(newTorsion - torsion) > 0.001)
00226         atoms->changeTorsion(torsion - newTorsion, atom1, atom2, atom3, atom4, true);
00227       else
00228         return; // no new value was entered
00229       break;
00230     }
00231     default: return;
00232   }
00233   setModified();
00234   updateAtomSet();
00235 }
00236 
00238 void GLMoleculeView::showDensity()
00240 {
00241   if(densityDialog == NULL)
00242   {
00243     densityDialog = new DensityBase(isoSurface, this);
00244     connect(densityDialog, SIGNAL(newSurface(const unsigned int)), this, SLOT(addGLSurface(const unsigned int)));
00245     connect(densityDialog, SIGNAL(updatedSurface(const unsigned int)), this, SLOT(updateGLSurface(const unsigned int)));
00246     connect(densityDialog, SIGNAL(deletedSurface(const unsigned int)), this, SLOT(deleteGLSurface(const unsigned int)));
00247     connect(densityDialog, SIGNAL(redrawScene()), this, SLOT(updateGL()));
00248   }
00249   densityDialog->show();
00250   if(!isoSurface->densityPresent())
00251     densityDialog->loadDensityA();
00252 }
00253 
00255 void GLMoleculeView::addAtoms()
00257 {
00258   if(newAtomDialog == NULL)
00259   {
00260     newAtomDialog = new NewAtomBase(atoms, this);
00261     connect(newAtomDialog, SIGNAL(atomAdded()), this, SLOT(updateAtomSet()));
00262     connect(newAtomDialog, SIGNAL(atomAdded()), this, SLOT(setModified()));
00263     connect(newAtomDialog, SIGNAL(atomAdded()), this, SIGNAL(atomsetChanged()));
00264   }
00265   newAtomDialog->show();
00266 }
00267 
00269 void GLMoleculeView::deleteSelectedAtoms()
00271 {
00272   if(selectionList.empty())
00273     return;
00274 
00276   // make a copy
00277   std::vector<unsigned int> sortedList;
00278   sortedList.reserve(selectionList.size());
00279   sortedList.assign(selectionList.begin(), selectionList.end());
00280   // sort it from largest to smallest
00281   std::sort(sortedList.begin(), sortedList.end(), std::greater<unsigned int>());
00282   // delete the atoms
00283   for(unsigned int i = 0; i < sortedList.size(); i++)
00284     atoms->removeAtom(sortedList[i]);
00285   // clear the selection
00286   unselectAll();
00287   if(newAtomDialog != 0)
00288     newAtomDialog->updateAtomLimits();
00289   updateAtomSet();
00290   setModified();
00291   emit atomsetChanged();
00292 }
00293 
00295 void GLMoleculeView::toggleSelection()
00297 {
00298   manipulateSelection = !manipulateSelection;
00299 }
00300 
00304 
00306 float GLMoleculeView::boundingSphereRadius()
00310 {
00311   float radius = GLSimpleMoleculeView::boundingSphereRadius();
00312 
00313   if(atoms->count() == 0 && isoSurface->densityPresent())
00314   {
00316     Point3D<float> origin = isoSurface->getOrigin();
00317     Point3D<float> delta = isoSurface->getDelta();
00318     Point3D<unsigned int> numPoints = isoSurface->getNumPoints();
00319     float x, y, z;
00320     std::vector<float> squaredR;
00321     // the current radius
00322     squaredR.push_back(static_cast<float>(radius*radius));
00323     // point 1: the origin
00324     x = origin.x() - centerX;
00325     y = origin.y() - centerY;
00326     z = origin.z() - centerZ;
00327     squaredR.push_back(x*x + y*y + z*z);
00328     // point 2: along the x-axis
00329     x = origin.x() + delta.x() * (numPoints.x() - 1) - centerX;
00330     y = origin.y() - centerY;
00331     z = origin.z() - centerZ;
00332     squaredR.push_back(x*x + y*y + z*z);
00333     // point 3: along the y-axis
00334     x = origin.x() - centerX;
00335     y = origin.y() + delta.y() * (numPoints.y() - 1) - centerY;
00336     z = origin.z() - centerZ;
00337     squaredR.push_back(x*x + y*y + z*z);
00338     // point 4: along the z-axis
00339     x = origin.x() - centerX;
00340     y = origin.y() - centerY;
00341     z = origin.z() + delta.z() * (numPoints.z() - 1) - centerZ;
00342     squaredR.push_back(x*x + y*y + z*z);
00343     // point 5: along the x and y axes
00344     x = origin.x() + delta.x() * (numPoints.x() - 1) - centerX;
00345     y = origin.y() + delta.y() * (numPoints.y() - 1) - centerY;
00346     z = origin.z() - centerZ;
00347     squaredR.push_back(x*x + y*y + z*z);
00348     // point 6: along the x and z axes
00349     x = origin.x() + delta.x() * (numPoints.x() - 1) - centerX;
00350     y = origin.y() - centerY;
00351     z = origin.z() + delta.z() * (numPoints.z() - 1) - centerZ;
00352     squaredR.push_back(x*x + y*y + z*z);
00353     // point 7: along the y and z axes
00354     x = origin.x() - centerX;
00355     y = origin.y() + delta.y() * (numPoints.y() - 1) - centerY;
00356     z = origin.z() + delta.z() * (numPoints.z() - 1) - centerZ;
00357     squaredR.push_back(x*x + y*y + z*z);
00358     // point 8: along all axes
00359     x = origin.x() + delta.x() * (numPoints.x() - 1) - centerX;
00360     y = origin.y() + delta.y() * (numPoints.y() - 1) - centerY;
00361     z = origin.z() + delta.z() * (numPoints.z() - 1) - centerZ;
00362     squaredR.push_back(x*x + y*y + z*z);
00363 
00364     float boxradius = sqrt(*(std::max_element(squaredR.begin(), squaredR.end())));
00365     qDebug("GLMoleculeView::boundingSphereRadius: boxradius = %f, radius = %f",boxradius, radius);
00366     if(boxradius > radius)
00367       radius = boxradius;
00368   }
00369   return radius;
00370 }
00371 
00373 void GLMoleculeView::mouseMoveEvent(QMouseEvent* e)
00376 {
00377   QPoint newPosition = e->pos();
00378   if(selectionType != SELECTION_NONE && e->state() & Qt::LeftButton && (manipulateSelection || e->state() & Qt::AltButton) && !(e->state() & Qt::ShiftButton && e->state() & Qt::ControlButton))
00379   {
00381     if(e->state() & Qt::ShiftButton)
00382     {
00385       if(abs(newPosition.y() - mousePosition.y()) > abs(newPosition.x() - mousePosition.x()))
00386         translateSelection(0, 0, newPosition.y() - mousePosition.y());
00387       else if(newPosition.x() != mousePosition.x())
00388         rotateSelection(0.0, 0.0, 180.0 * static_cast<double>(newPosition.x() - mousePosition.x()) / static_cast<double>(width()));
00389     }
00390     else if(e->state() & Qt::ControlButton)
00393       translateSelection(newPosition.x() - mousePosition.x(), newPosition.y() - mousePosition.y(), 0);
00394     else
00397       rotateSelection(-180.0 * static_cast<double>(newPosition.y() - mousePosition.y()) / static_cast<double>(height()),
00398                       -180.0 * static_cast<double>(newPosition.x() - mousePosition.x()) / static_cast<double>(width()), 0.0);
00399   }
00400   else if(selectionType >= SELECTION_BOND && selectionType <= SELECTION_TORSION && e->state() & Qt::LeftButton && e->state() & Qt::ShiftButton && e->state() & Qt::ControlButton)
00402     changeSelectedIC(e->pos().x() - mousePosition.x());
00403   else
00404     GLView::mouseMoveEvent(e); // normal manipulation of entire system
00405 
00406   mousePosition = newPosition;
00407 }
00408 
00410 void GLMoleculeView::keyPressEvent(QKeyEvent* e)
00413 {
00414   if(selectionType != SELECTION_NONE && (manipulateSelection || e->state() & Qt::AltButton) && !(e->state() & Qt::ShiftButton && e->state() & Qt::ControlButton))
00415   {
00416     switch(e->key())
00417     {
00418       case Qt::Key_Left : if(e->state() & Qt::ShiftButton)
00419                             rotateSelection(0.0, 0.0, -5.0);
00420                           else if(e->state() & Qt::ControlButton)
00421                             translateSelection(-5, 0, 0);
00422                           else
00423                             rotateSelection(0.0, 5.0, 0.0);
00424                           break;
00425 
00426       case Qt::Key_Up   : if(e->state() & Qt::ShiftButton)
00427                             translateSelection(0, 0, -5);
00428                           else if(e->state() & Qt::ControlButton)
00429                             translateSelection(0, -5, 0);
00430                           else
00431                             rotateSelection(5.0, 0.0, 0.0);
00432                           break;
00433 
00434       case Qt::Key_Right: if(e->state() & Qt::ShiftButton)
00435                             rotateSelection(0.0, 0.0, 5.0);
00436                           else if(e->state() & Qt::ControlButton)
00437                             translateSelection(5, 0, 0);
00438                           else
00439                             rotateSelection(0.0, -5.0, 0.0);
00440                           break;
00441 
00442       case Qt::Key_Down : if(e->state() & Qt::ShiftButton)
00443                             translateSelection(0, 0, 5);
00444                           else if(e->state() & Qt::ControlButton)
00445                             translateSelection(0, 5, 0);
00446                           else
00447                             rotateSelection(-5.0, 0.0, 0.0);
00448                           break;
00449 
00450       //default:            e->ignore();
00451       //                    return;
00452     }
00453   }
00454   else if(selectionType >= SELECTION_BOND && selectionType <= SELECTION_TORSION && e->state() & Qt::ShiftButton && e->state() & Qt::ControlButton)
00455   {
00456     switch(e->key())
00457     {
00458       case Qt::Key_Left : changeSelectedIC(-1);
00459                           break;
00460       case Qt::Key_Right: changeSelectedIC(1);
00461                           break;
00462       //default:            e->ignore();
00463       //                    return;
00464     }
00465   }
00466   else
00467     GLSimpleMoleculeView::keyPressEvent(e);
00468 }
00469 
00471 void GLMoleculeView::updateShapes()
00474 {
00475   GLSimpleMoleculeView::updateShapes(); // first the shapes of the base class
00476 
00477   ShapeProperties prop;
00478 
00480   for(unsigned int i = 0; i < isoSurface->numSurfaces(); i++)
00481   {
00482     prop.id = i;
00483     if(densityDialog->surfaceType(i) == 0)
00484       prop.opacity = densityDialog->surfaceOpacity(i);
00485     else
00486       prop.opacity = 100;
00487     prop.type = SHAPE_SURFACE;
00488     shapes.push_back(prop);
00489   }
00490 }
00491 
00495 
00497 void GLMoleculeView::addGLSurface(const unsigned int index)
00499 {
00501   makeCurrent();
00502   GLuint newList = glGenLists(1);
00503   glSurfaces.push_back(newList);
00504 
00506   if(glSurfaces.size() == 1 && atoms->count() == 0)
00507     zoomFit(false);
00508 
00509   qDebug("creating surface %d", index);
00511   updateGLSurface(index);
00512 }
00513 
00515 void GLMoleculeView::updateGLSurface(const unsigned int index)
00517 {
00518   makeCurrent();
00519   QColor surfaceColor = densityDialog->surfaceColor(index);
00520   unsigned int surfaceOpacity = densityDialog->surfaceOpacity(index);
00521   Point3D<float> point1, point2, point3, normal1, normal2, normal3;
00522 
00523   qDebug("updating surface %d", index);
00524   qDebug(" which consists of %d vertices and %d triangles",isoSurface->numVertices(index),isoSurface->numTriangles(index));
00525   qDebug(" with color %d, %d, %d and opacity %d", surfaceColor.red(), surfaceColor.green(), surfaceColor.blue(), surfaceOpacity);
00526   glNewList(glSurfaces[index], GL_COMPILE);
00527     switch(densityDialog->surfaceType(index))
00528     {
00529       case 0: // Solid surface
00530         glBegin(GL_TRIANGLES);
00531           glColor4d(surfaceColor.red()/255.0, surfaceColor.green()/255.0, surfaceColor.blue()/255, surfaceOpacity/100.0);
00532                 for(unsigned int i = 0; i < isoSurface->numTriangles(index); i++)
00533                 {
00534             isoSurface->getTriangle(index, i, point1, point2, point3, normal1, normal2, normal3);
00535                     glNormal3f(normal1.x(), normal1.y(), normal1.z());
00536             glVertex3f(point1.x(), point1.y(), point1.z());
00537                         glNormal3f(normal2.x(), normal2.y(), normal2.z());
00538             glVertex3f(point2.x(), point2.y(), point2.z());
00539                         glNormal3f(normal3.x(), normal3.y(), normal3.z());
00540             glVertex3f(point3.x(), point3.y(), point3.z());
00541                 }
00542         glEnd();
00543         break;
00544       case 1: // Wireframe
00545         //glLineWidth(1.0);
00546         {
00547           double lw, ps;
00548           glGetDoublev(GL_LINE_WIDTH, &lw);
00549           glGetDoublev(GL_POINT_SIZE, &ps);
00550           qDebug("linewidth and pointsize used for generating: %f and %f", lw, ps);
00551         }
00552         glBegin(GL_LINES);
00553           glColor3d(surfaceColor.red()/255.0, surfaceColor.green()/255.0, surfaceColor.blue()/255.0);
00554                 for(unsigned int i = 0; i < isoSurface->numTriangles(index); i++)
00555                 {
00556             isoSurface->getTriangle(index, i, point1, point2, point3, normal1, normal2, normal3);
00557             glVertex3f(point1.x(), point1.y(), point1.z());
00558                         glVertex3f(point2.x(), point2.y(), point2.z());
00559             glVertex3f(point1.x(), point1.y(), point1.z());
00560             glVertex3f(point3.x(), point3.y(), point3.z());
00561                         glVertex3f(point2.x(), point2.y(), point2.z());
00562             glVertex3f(point3.x(), point3.y(), point3.z());
00563                 }
00564         glEnd();
00565         break;
00566       case 2: // Dots
00567         glPointSize(1.0);
00568         glBegin(GL_POINTS);
00569           glColor3d(surfaceColor.red()/255.0, surfaceColor.green()/255.0, surfaceColor.blue()/255.0);
00570                 for(unsigned int i = 0; i < isoSurface->numVertices(index); i++)
00571                 {
00572             point1 = isoSurface->getPoint(index, i);
00573             glVertex3f(point1.x(), point1.y(), point1.z());
00574           }
00575         glEnd();
00576     }
00577   glEndList();
00578   reorderShapes();
00579 }
00580 
00582 void GLMoleculeView::deleteGLSurface(const unsigned int index)
00584 {
00585   makeCurrent();
00586   glDeleteLists(glSurfaces[index], 1);
00587   std::vector<GLuint>::iterator it = glSurfaces.begin();
00588   it += index;
00589   glSurfaces.erase(it);
00590   reorderShapes();
00591 }
00592 
00596 
00598 void GLMoleculeView::translateSelection(const int xRange, const int yRange, const int zRange)
00600 {
00601   if(selectionList.empty())
00602     return;
00603 
00604   makeCurrent();
00605   // needed variables
00606   GLdouble modelview[16];
00607   GLdouble projection[16];
00608   GLint viewport[4];
00609 
00610   // set up the modelview matrix to be the same as in paintGL
00611   Vector3D<float> axis;
00612   float angle;
00613   orientationQuaternion->getAxisAngle(axis, angle);
00614   glPushMatrix();
00615   glTranslatef(xPos, yPos, 0.0f);
00616   glRotatef(angle, axis.x(), axis.y(), axis.z());
00617   glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
00618   glPopMatrix();
00619 
00620   // get the other matrices
00621   glGetDoublev(GL_PROJECTION_MATRIX, projection);
00622   glGetIntegerv(GL_VIEWPORT, viewport);
00623 
00625   GLdouble x, y, z, xwin, ywin, zwin;
00626   std::list<unsigned int>::iterator it = selectionList.begin();
00627 
00628   // get the data
00629   x = atoms->x(*it);
00630   y = atoms->y(*it);
00631   z = atoms->z(*it);
00632 
00633   // map the atom coordinates to the window coordinates with gluProject
00634   if(gluProject(x, y, z, modelview, projection, viewport, &xwin, &ywin, &zwin) == GL_FALSE)
00635     return;
00636 
00637   // do the translation in window coordinates
00638   xwin += static_cast<double>(xRange);
00639   ywin -= static_cast<double>(yRange); // OpenGL coordinate system inverts the y-axis
00640   if(baseParameters.perspectiveProjection)
00641     zwin += static_cast<double>(zRange)/10000.0; // (10000 = far clipping distance/near clipping distance)
00642   else
00643     zwin += static_cast<double>(zRange)/100.0;
00644     //zwin += static_cast<double>(zRange)/(2.0f*boundingSphereRadius()); // is very slow!!!
00645 
00646   // map the new window coordinates to the atom coordinates with gluUnproject
00647   if(gluUnProject(xwin, ywin, zwin, modelview, projection, viewport, &x, &y, &z) == GL_FALSE)
00648     return;
00649 
00650   // determine the translation vector
00651   const double dx = x - atoms->x(*it);
00652   const double dy = y - atoms->y(*it);
00653   const double dz = z - atoms->z(*it);
00654 
00655   // apply this translation vector to all selected atoms
00656   while(it != selectionList.end())
00657   {
00658     atoms->setX(*it, atoms->x(*it) + dx);
00659     atoms->setY(*it, atoms->y(*it) + dy);
00660     atoms->setZ(*it, atoms->z(*it) + dz);
00661     it++;
00662   }
00663 
00664   updateAtomSet();
00665   setModified();
00666 }
00667 
00669 void GLMoleculeView::rotateSelection(const double angleX, const double angleY, const double angleZ)
00671 {
00672   if(selectionList.empty())
00673     return;
00674 
00679   //* original version working with 3 successive axis/angle rotations
00680   Vector3D<double> axis;
00681   double angle;
00682   Quaternion<double> q(angleX, angleY, angleZ);
00683   q.getAxisAngle(axis, angle);
00684   Vector3D<float> axis2;
00685   float angle2;
00686   orientationQuaternion->getAxisAngle(axis2, angle2);
00687   double backAngle = - angle2;
00688   Vector3D<double> backAxis(axis2.x(), axis2.y(), axis2.z());
00689   // */
00690   /* construct the desired quaternions in double precision -> doesn't seem to work correctly
00691   Quaternion<double> orientation(static_cast<double>(orientationQuaternion->w()), static_cast<double>(orientationQuaternion->x()),
00692                                static_cast<double>(orientationQuaternion->y()), static_cast<double>(orientationQuaternion->z()));
00693   Quaternion<double> backOrientation(orientation);
00694   backOrientation.inverse();
00695   Quaternion<double> rotation(angleX, angleY, angleZ);
00696   Quaternion<double> totalRotation = backOrientation * rotation * orientation;
00697   // get the axis/angle representation
00698   Vector3D<double> axis;
00699   double angle;
00700   totalRotation.getAxisAngle(axis, angle);
00701   */
00702   if(fabs(angle) < Point3D<double>::TOLERANCE)
00703     return;
00704 
00706   Point3D<double> centerOfMass(0.0, 0.0, 0.0);
00707   std::list<unsigned int>::iterator it = selectionList.begin();
00708   while(it != selectionList.end())
00709     centerOfMass.add(atoms->coordinates(*it++));
00710   centerOfMass.setValues(centerOfMass.x()/selectionList.size(), centerOfMass.y()/selectionList.size(), centerOfMass.z()/selectionList.size());
00711   //qDebug("centerOfMass = %f, %f, %f", centerOfMass.x(), centerOfMass.y(), centerOfMass.z());
00712 
00714   it = selectionList.begin();
00715   while(it != selectionList.end())
00716   {
00717     Vector3D<double> v(centerOfMass, atoms->coordinates(*it));
00718     //v.rotate(axis, angle);
00719     v.rotate(backAxis, backAngle);
00720     v.rotate(axis, angle);
00721     v.rotate(backAxis, -backAngle);
00722     atoms->setX(*it, centerOfMass.x() + v.x());
00723     atoms->setY(*it, centerOfMass.y() + v.y());
00724     atoms->setZ(*it, centerOfMass.z() + v.z());
00725     it++;
00726   }
00727   updateAtomSet();
00728   setModified();
00729 }
00730 
00732 void GLMoleculeView::changeSelectedIC(const int range)
00735 {
00736   if(range == 0)
00737     return;
00738 
00739   unsigned int atom1, atom2, atom3, atom4;
00740   std::list<unsigned int>::iterator it = selectionList.begin();
00741   switch(selectionType)
00742   {
00743     case SELECTION_BOND:    atom1 = *it++;
00744                             atom2 = *it;
00745                             atoms->changeBond(static_cast<double>(range) * 0.1, atom1, atom2, true);
00746                             break;
00747 
00748     case SELECTION_ANGLE:   atom1 = *it++;
00749                             atom2 = *it++;
00750                             atom3 = *it;
00751                             atoms->changeAngle(180.0 * static_cast<double>(range) / static_cast<double>(width()), atom1, atom2, atom3, true);
00752                             break;
00753     case SELECTION_TORSION: atom1 = *it++;
00754                             atom2 = *it++;
00755                             atom3 = *it++;
00756                             atom4 = *it;
00757                             atoms->changeTorsion(-180.0 * static_cast<double>(range) / static_cast<double>(width()), atom1, atom2, atom3, atom4, true);
00758                             break;
00759   }
00760   updateAtomSet();
00761   setModified();
00762 }
00763 
00765 void GLMoleculeView::drawItem(const unsigned int index)
00767 {
00768   if(shapes[index].type != SHAPE_SURFACE)
00769     return; // this routine only draws isosurfaces at the moment
00770 
00771   const unsigned int currentSurface = shapes[index].id;
00772   if(currentSurface >= isoSurface->numSurfaces())
00773     return; // asked to draw a non-existing surface
00774 
00775   if(densityDialog->surfaceVisible(currentSurface))
00776   {
00777     if(densityDialog->surfaceType(currentSurface) == 0)
00778     {
00779       glCallList(glSurfaces[currentSurface]);
00780     }
00781     else
00782     {
00783       glDisable(GL_LIGHTING);
00784       glCallList(glSurfaces[currentSurface]);
00785       glEnable(GL_LIGHTING);
00786     }
00787   }
00788 }
00789 

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