• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

kalzium

bsdyengine.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002   BSDYEngine - Dynamic detail engine for "balls and sticks" display
00003 
00004   Copyright (C) 2007 Donald Ephraim Curtis
00005 
00006   This file is part of the Avogadro molecular editor project.
00007   For more information, see <http://avogadro.sourceforge.net/>
00008 
00009   Avogadro is free software; you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation; either version 2 of the License, or
00012   (at your option) any later version.
00013 
00014   Avogadro is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU General Public License for more details.
00018 
00019   You should have received a copy of the GNU General Public License
00020   along with this program; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00022   02110-1301, USA.
00023  **********************************************************************/
00024 
00025 #include "bsdyengine.h"
00026 
00027 #include <config.h>
00028 #include <avogadro/camera.h>
00029 #include <avogadro/painter.h>
00030 #include <avogadro/color.h>
00031 
00032 #include <QGLWidget> // for OpenGL bits
00033 #include <QDebug>
00034 
00035 using namespace std;
00036 using namespace OpenBabel;
00037 using namespace Eigen;
00038 
00039 namespace Avogadro
00040 {
00041 
00042 // our sort function
00043   Camera *camera = 0;
00044   bool sortCameraFarthest( const Primitive* lhs, const Primitive* rhs )
00045   {
00046     if ( !lhs ) {
00047       if ( rhs ) {
00048         return true;
00049       } else {
00050         return false;
00051       }
00052     }
00053 
00054     if ( lhs->type() == Primitive::BondType && rhs->type() == Primitive::BondType ) {
00055       if ( camera ) {
00056         const Bond *l = static_cast<const Bond *>( lhs );
00057         const Bond *r = static_cast<const Bond *>( rhs );
00058 
00059         const Atom* latom1 = static_cast<const Atom *>( l->GetBeginAtom() );
00060         const Atom* latom2 = static_cast<const Atom *>( l->GetEndAtom() );
00061         Vector3d lv1( latom1->pos() );
00062         Vector3d lv2( latom2->pos() );
00063         Vector3d ld1 = lv2 - lv1;
00064         ld1.normalize();
00065 
00066         const Atom* ratom1 = static_cast<const Atom *>( r->GetBeginAtom() );
00067         const Atom* ratom2 = static_cast<const Atom *>( r->GetEndAtom() );
00068         Vector3d rv1( ratom1->pos() );
00069         Vector3d rv2( ratom2->pos() );
00070         Vector3d rd1 = rv2 - rv1;
00071         return camera->distance( ld1 ) >= camera->distance( rd1 );
00072       }
00073     } else if ( lhs->type() == Primitive::AtomType && rhs->type() == Primitive::AtomType ) {
00074       if ( camera ) {
00075         const Atom *l = static_cast<const Atom*>( lhs );
00076         const Atom *r = static_cast<const Atom*>( rhs );
00077         return camera->distance( l->pos() ) >= camera->distance( r->pos() );
00078       }
00079     }
00080     return false;
00081   }
00082 
00083   BSDYEngine::BSDYEngine( QObject *parent ) : Engine( parent ),
00084       m_settingsWidget( 0 ), m_atomRadiusPercentage( 0.3 ), m_bondRadius( 0.1 ),
00085       m_showMulti(true)
00086   {
00087     setDescription( tr( "Renders primitives using Balls (atoms) and Sticks (bonds)." ) );
00088 
00089   }
00090 
00091   Engine *BSDYEngine::clone() const
00092   {
00093     BSDYEngine *engine = new BSDYEngine(parent());
00094     engine->setName(name());
00095     engine->m_atomRadiusPercentage = m_atomRadiusPercentage;
00096     engine->m_bondRadius = m_bondRadius;
00097     engine->m_showMulti = m_showMulti;
00098     engine->setEnabled(isEnabled());
00099 
00100     return engine;
00101   }
00102 
00103   BSDYEngine::~BSDYEngine()
00104   {
00105     if ( m_settingsWidget ) {
00106       m_settingsWidget->deleteLater();
00107     }
00108 
00109   }
00110 
00111   bool BSDYEngine::renderOpaque( PainterDevice *pd )
00112   {
00113     QList<Primitive *> list;
00114 
00115     glPushAttrib( GL_TRANSFORM_BIT );
00116 
00117     Color *map = colorMap(); // possible custom color map
00118     if (!map) map = pd->colorMap(); // fall back to global color map
00119 
00120     // Get a list of bonds and render them
00121     list = primitives().subList( Primitive::BondType );
00122 
00123     foreach(const Primitive *p, list ) {
00124       const Bond *b = static_cast<const Bond *>( p );
00125 
00126       const Atom* atom1 = static_cast<const Atom *>( b->GetBeginAtom() );
00127       const Atom* atom2 = static_cast<const Atom *>( b->GetEndAtom() );
00128       Vector3d v1( atom1->pos() );
00129       Vector3d v2( atom2->pos() );
00130       Vector3d d = v2 - v1;
00131       d.normalize();
00132       Vector3d v3(( v1 + v2 + d*( radius( atom1 )-radius( atom2 ) ) ) / 2 );
00133 
00134       double shift = 0.15;
00135       int order = 1;
00136       if (m_showMulti) order = b->GetBO();
00137 
00138       map->set( atom1 );
00139       pd->painter()->setColor( map );
00140       pd->painter()->setName( b );
00141       pd->painter()->drawMultiCylinder( v1, v3, m_bondRadius, order, shift );
00142 
00143       map->set( atom2 );
00144       pd->painter()->setColor( map );
00145       pd->painter()->setName( b );
00146       pd->painter()->drawMultiCylinder( v3, v2, m_bondRadius, order, shift );
00147     }
00148 
00149     glDisable( GL_NORMALIZE );
00150     glEnable( GL_RESCALE_NORMAL );
00151 
00152     // Build up a list of the atoms and render them
00153     list = primitives().subList( Primitive::AtomType );
00154     foreach(const Primitive *p, list ) {
00155       const Atom *a = static_cast<const Atom *>( p );
00156 
00157       map->set( a );
00158       pd->painter()->setColor( map );
00159       pd->painter()->setName( a );
00160       pd->painter()->drawSphere( a->pos(), radius( a ) );
00161     }
00162 
00163     // normalize normal vectors of bonds
00164     glDisable( GL_RESCALE_NORMAL );
00165     glEnable( GL_NORMALIZE );
00166 
00167     glPopAttrib();
00168 
00169     return true;
00170   }
00171 
00172   bool BSDYEngine::renderTransparent( PainterDevice *pd )
00173   {
00174     QList<Primitive *> list;
00175 
00176     camera = pd->camera();
00177 
00178     glPushAttrib( GL_TRANSFORM_BIT );
00179 
00180     Color *map = colorMap(); // possible custom color map
00181     if (!map) map = pd->colorMap(); // fall back to global color map
00182 
00183     // Get a list of bonds and render them
00184     list = primitives().subList( Primitive::BondType );
00185 
00186     // sort our atom list
00187     // qSort(list.begin(), list.end(), sortCameraFarthest);
00188 
00189     // enable depth mast for bonds
00190     glDepthMask( GL_TRUE );
00191 
00192     // push bond type
00193     foreach(const Primitive *p, list ) {
00194       const Bond *b = static_cast<const Bond *>( p );
00195 
00196       // Render the selection highlight
00197       if ( pd->isSelected( b ) ) {
00198         const Atom* atom1 = static_cast<const Atom *>( b->GetBeginAtom() );
00199         const Atom* atom2 = static_cast<const Atom *>( b->GetEndAtom() );
00200         Vector3d v1( atom1->pos() );
00201         Vector3d v2( atom2->pos() );
00202 
00203         double shift = 0.15;
00204         int order = b->GetBO();
00205 
00206         map->setToSelectionColor();
00207         glEnable( GL_BLEND );
00208         pd->painter()->setColor( map );
00209         pd->painter()->setName( b );
00210         if (order == 1)
00211           pd->painter()->drawCylinder(v1, v2, SEL_BOND_EXTRA_RADIUS + m_bondRadius);
00212         else
00213           pd->painter()->drawMultiCylinder( v1, v2, SEL_BOND_EXTRA_RADIUS + m_bondRadius, order, shift );
00214         glDisable( GL_BLEND );
00215       }
00216     }
00217 
00218     glDepthMask( GL_FALSE );
00219     glDisable( GL_NORMALIZE );
00220     glEnable( GL_RESCALE_NORMAL );
00221 
00222     // Build up a list of the atoms and render them
00223     list = primitives().subList( Primitive::AtomType );
00224 
00225     // sort our atom list
00226     // qSort(list.begin(), list.end(), sortCameraFarthest);
00227 
00228     foreach(const Primitive *p, list ) {
00229       const Atom *a = static_cast<const Atom *>( p );
00230 
00231       // Render the selection highlight
00232       if ( pd->isSelected( a ) ) {
00233         map->setToSelectionColor();
00234         glEnable( GL_BLEND );
00235         pd->painter()->setColor( map );
00236         pd->painter()->setName( a );
00237         pd->painter()->drawSphere( a->pos(), SEL_ATOM_EXTRA_RADIUS + radius( a ) );
00238         glDisable( GL_BLEND );
00239       }
00240     }
00241 
00242     // normalize normal vectors of bonds
00243     glDisable( GL_RESCALE_NORMAL );
00244     glEnable( GL_NORMALIZE );
00245 
00246     glPopAttrib();
00247 
00248     return true;
00249   }
00250 
00251   bool BSDYEngine::renderQuick(PainterDevice *pd)
00252   {
00253     // Render atoms and bond with no transparency...
00254     QList<Primitive *> list;
00255 
00256     Color *map = colorMap(); // possible custom color map
00257     if (!map) map = pd->colorMap(); // fall back to global color map
00258     Color cSel;
00259     cSel.setToSelectionColor();
00260 
00261     // Get a list of bonds and render them
00262     list = primitives().subList(Primitive::BondType);
00263 
00264     foreach(const Primitive *p, list)
00265     {
00266       const Bond *b = static_cast<const Bond *>(p);
00267 
00268       const Atom* atom1 = static_cast<const Atom *>(b->GetBeginAtom());
00269       const Atom* atom2 = static_cast<const Atom *>(b->GetEndAtom());
00270       Vector3d v1(atom1->pos());
00271       Vector3d v2(atom2->pos());
00272       Vector3d d = v2 - v1;
00273       d.normalize();
00274       Vector3d v3((v1 + v2 + d*(radius(atom1)-radius(atom2))) / 2);
00275 
00276       double shift = 0.15;
00277       int order = 1;
00278       if (m_showMulti) order = b->GetBO();
00279 
00280       if (pd->isSelected(b))
00281       {
00282         pd->painter()->setColor(&cSel);
00283         pd->painter()->setName(b);
00284         pd->painter()->drawMultiCylinder(v1, v2, SEL_BOND_EXTRA_RADIUS +
00285                                          m_bondRadius, order, shift);
00286       }
00287       else
00288       {
00289         map->set(atom1);
00290         pd->painter()->setColor(map);
00291         pd->painter()->setName(b);
00292         pd->painter()->drawMultiCylinder(v1, v3, m_bondRadius, order, shift);
00293 
00294         map->set( atom2 );
00295         pd->painter()->setColor(map);
00296         pd->painter()->setName(b);
00297         pd->painter()->drawMultiCylinder(v3, v2, m_bondRadius, order, shift);
00298       }
00299     }
00300 
00301     glDisable(GL_NORMALIZE);
00302     glEnable(GL_RESCALE_NORMAL);
00303 
00304     // Build up a list of the atoms and render them
00305     list = primitives().subList(Primitive::AtomType);
00306     foreach(const Primitive *p, list)
00307     {
00308       const Atom *a = static_cast<const Atom *>(p);
00309 
00310       if (pd->isSelected(a))
00311       {
00312         pd->painter()->setColor(&cSel);
00313         pd->painter()->setName(a);
00314         pd->painter()->drawSphere(a->pos(), SEL_ATOM_EXTRA_RADIUS + radius(a));
00315       }
00316       else
00317       {
00318         map->set(a);
00319         pd->painter()->setColor(map);
00320         pd->painter()->setName(a);
00321         pd->painter()->drawSphere(a->pos(), radius(a));
00322       }
00323     }
00324 
00325     // normalize normal vectors of bonds
00326     glDisable(GL_RESCALE_NORMAL);
00327     glEnable(GL_NORMALIZE);
00328     return true;
00329   }
00330 
00331   inline double BSDYEngine::radius( const Atom *atom ) const
00332   {
00333     return etab.GetVdwRad( atom->GetAtomicNum() ) * m_atomRadiusPercentage;
00334   }
00335 
00336   void BSDYEngine::setAtomRadiusPercentage( int percent )
00337   {
00338     m_atomRadiusPercentage = 0.1 * percent;
00339     emit changed();
00340   }
00341 
00342   void BSDYEngine::setBondRadius( int value )
00343   {
00344     m_bondRadius = value * 0.05;
00345     emit changed();
00346   }
00347 
00348   void BSDYEngine::setShowMulti(int value)
00349   {
00350     m_showMulti = value;
00351     emit changed();
00352   }
00353 
00354   double BSDYEngine::radius( const PainterDevice *pd, const Primitive *p ) const
00355   {
00356     // Atom radius
00357     if ( p->type() == Primitive::AtomType ) {
00358       if ( pd ) {
00359         if ( pd->isSelected( p ) )
00360           return radius( static_cast<const Atom *>( p ) ) + SEL_ATOM_EXTRA_RADIUS;
00361       }
00362       return radius( static_cast<const Atom *>( p ) );
00363     }
00364     // Bond radius
00365     else if ( p->type() == Primitive::BondType ) {
00366       if ( pd ) {
00367         if ( pd->isSelected( p ) )
00368           return m_bondRadius + SEL_BOND_EXTRA_RADIUS;
00369       }
00370       return m_bondRadius;
00371     }
00372     // Something else
00373     else
00374       return 0.;
00375   }
00376 
00377   double BSDYEngine::transparencyDepth() const
00378   {
00379     return m_atomRadiusPercentage;
00380   }
00381 
00382   QWidget *BSDYEngine::settingsWidget()
00383   {
00384     if (!m_settingsWidget) {
00385       m_settingsWidget = new BSDYSettingsWidget();
00386       connect(m_settingsWidget->atomRadiusSlider, SIGNAL(valueChanged(int)), this, SLOT(setAtomRadiusPercentage(int)));
00387       connect(m_settingsWidget->bondRadiusSlider, SIGNAL(valueChanged(int)), this, SLOT(setBondRadius(int)));
00388       connect(m_settingsWidget->showMulti, SIGNAL(stateChanged(int)), this, SLOT(setShowMulti(int)));
00389       connect(m_settingsWidget, SIGNAL(destroyed()), this, SLOT(settingsWidgetDestroyed()));
00390       m_settingsWidget->atomRadiusSlider->setValue(10*m_atomRadiusPercentage);
00391       m_settingsWidget->bondRadiusSlider->setValue(20*m_bondRadius);
00392       m_settingsWidget->showMulti->setCheckState((Qt::CheckState)m_showMulti);
00393     }
00394     return m_settingsWidget;
00395   }
00396 
00397   void BSDYEngine::settingsWidgetDestroyed()
00398   {
00399     qDebug() << "Destroyed Settings Widget";
00400     m_settingsWidget = 0;
00401   }
00402 
00403   void BSDYEngine::writeSettings(QSettings &settings) const
00404   {
00405     Engine::writeSettings(settings);
00406     settings.setValue("atomRadius", 10*m_atomRadiusPercentage);
00407     settings.setValue("bondRadius", 20*m_bondRadius);
00408     settings.setValue("showMulti", m_showMulti);
00409   }
00410 
00411   void BSDYEngine::readSettings(QSettings &settings)
00412   {
00413     Engine::readSettings(settings);
00414     setAtomRadiusPercentage(settings.value("atomRadius", 3).toInt());
00415     setBondRadius(settings.value("bondRadius", 2).toInt());
00416     setShowMulti(settings.value("showMulti", 2).toInt());
00417 
00418     if (m_settingsWidget) {
00419       m_settingsWidget->atomRadiusSlider->setValue(10*m_atomRadiusPercentage);
00420       m_settingsWidget->bondRadiusSlider->setValue(20*m_bondRadius);
00421       m_settingsWidget->showMulti->setCheckState((Qt::CheckState)m_showMulti);
00422     }
00423   }
00424 
00425 
00426   Engine::EngineFlags BSDYEngine::flags() const
00427   {
00428     return Engine::Transparent | Engine::Atoms | Engine::Bonds;
00429   }
00430 //   AVOGADRO_ENGINE_FACTORY(BSDYEngine)
00431 
00432 }
00433 
00434 #include "bsdyengine.moc"
00435 
00436 Q_EXPORT_PLUGIN2( bsdyengine, Avogadro::BSDYEngineFactory )

kalzium

Skip menu "kalzium"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal