1
/**********************************************************************
2
Animation - Basic animation
4
Copyright (C) 2008 by Tim Vandermeersch
5
Copyright (C) 2009 by Geoffrey Hutchison
7
This file is part of the Avogadro molecular editor project.
8
For more information, see <http://avogadro.openmolecules.net/>
10
Some code is based on Open Babel
11
For more information, see <http://openbabel.sourceforge.net/>
13
This program is free software; you can redistribute it and/or modify
14
it under the terms of the GNU General Public License as published by
15
the Free Software Foundation version 2 of the License.
17
This program is distributed in the hope that it will be useful,
18
but WITHOUT ANY WARRANTY; without even the implied warranty of
19
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
GNU General Public License for more details.
21
***********************************************************************/
23
#include "animation.h"
25
#include <avogadro/molecule.h>
26
#include <avogadro/atom.h>
27
#include <avogadro/bond.h>
28
#include <openbabel/mol.h>
33
using namespace OpenBabel;
34
using Eigen::Vector3d;
38
class AnimationPrivate
41
AnimationPrivate() : fps(25), framesSet(false), dynamicBonds(false) {}
48
Animation::Animation(QObject *parent) : QObject(parent), d(new AnimationPrivate),
49
m_molecule(0), m_timeLine(new QTimeLine)
51
// in chemical animations, each frame should take the same time
52
m_timeLine->setCurveShape(QTimeLine::LinearCurve);
55
Animation::~Animation()
65
void Animation::setMolecule(Molecule *molecule)
67
m_molecule = molecule;
69
return; // we can't save the current conformers
72
m_originalConformers.clear();
73
for (unsigned int i = 0; i < molecule->numConformers(); ++i) {
74
m_originalConformers.push_back(molecule->conformer(i));
77
m_timeLine->setFrameRange( 1, m_molecule->numConformers() );
81
int Animation::numFrames() const
84
return m_frames.size();
86
return m_molecule->numConformers();
90
int Animation::fps() const
95
void Animation::setFps(int fps)
100
int Animation::loopCount() const
102
return m_timeLine->loopCount();
105
void Animation::setLoopCount(int loops)
107
m_timeLine->setLoopCount(loops);
110
void Animation::setFrame(int i)
112
if (i <= 0 || !m_molecule || i > (int)m_molecule->numConformers())
113
return; // nothing to do
115
m_molecule->lock()->lockForWrite();
116
m_molecule->setConformer(i-1); // Frame counting starts from 1
118
if (d->dynamicBonds) {
119
// construct minimal OBMol
120
OpenBabel::OBMol obmol;
122
foreach(Atom *atom, m_molecule->atoms()) {
123
OpenBabel::OBAtom *a = obmol.NewAtom();
124
OpenBabel::OBAtom obatom = atom->OBAtom();
130
obmol.ConnectTheDots();
132
QList<Bond*> bonds(m_molecule->bonds());
133
foreach(Bond *bond, bonds)
134
m_molecule->removeBond(bond->id());
136
FOR_BONDS_OF_MOL (obbond, obmol) {
137
Bond *bond = m_molecule->addBond();
138
bond->setBegin(m_molecule->atom(obbond->GetBeginAtomIdx()-1));
139
bond->setEnd(m_molecule->atom(obbond->GetEndAtomIdx()-1));
140
bond->setOrder(obbond->GetBondOrder());
143
m_molecule->lock()->unlock();
144
m_molecule->update();
145
emit frameChanged(i);
148
bool Animation::dynamicBonds() const
150
return d->dynamicBonds;
153
void Animation::setDynamicBonds(bool enable)
155
d->dynamicBonds = enable;
158
void Animation::setFrames(std::vector< std::vector< Eigen::Vector3d> *> frames)
160
if (frames.size() == 0)
161
return; // nothing to do
163
if (!m_originalConformers.empty())
164
m_originalConformers.clear();
166
for (unsigned int i = 0; i < m_molecule->numConformers(); ++i) {
167
m_originalConformers.push_back(m_molecule->conformer(i));
173
m_timeLine->setFrameRange(1, numFrames() );
176
void Animation::stop()
182
m_timeLine->setCurrentTime(0);
183
disconnect(m_timeLine, SIGNAL(frameChanged(int)),
184
this, SLOT(setFrame(int)));
186
// restore original conformers
188
m_molecule->lock()->lockForWrite();
189
m_molecule->setAllConformers(m_originalConformers);
190
m_molecule->lock()->unlock();
195
void Animation::start()
200
// set molecule conformers
202
m_molecule->lock()->lockForWrite();
203
// don't delete the existing conformers -- we save them as m_originalConformers
204
m_molecule->setAllConformers(m_frames, false);
205
m_molecule->lock()->unlock();
210
int interval = 1000 / d->fps;
211
m_timeLine->setUpdateInterval(interval);
212
int duration = interval * numFrames();
213
m_timeLine->setDuration(duration);
214
m_timeLine->setFrameRange( 1,numFrames() );
216
connect(m_timeLine, SIGNAL(frameChanged(int)),
217
this, SLOT(setFrame(int)));
219
m_timeLine->setCurrentTime(0);
223
void Animation::pause()
228
} // end namespace Avogadro