~benomrane-b/avogadro/avogadro

« back to all changes in this revision

Viewing changes to libavogadro/src/animation.cpp

  • Committer: benomrane_b at yahoo
  • Date: 2014-07-02 17:22:21 UTC
  • Revision ID: benomrane_b@yahoo.fr-20140702172221-vf3hdle85h6szhhf
Release version 1.1.1 2013-12-11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
  Animation - Basic animation
 
3
 
 
4
  Copyright (C) 2008 by Tim Vandermeersch
 
5
  Copyright (C) 2009 by Geoffrey Hutchison
 
6
 
 
7
  This file is part of the Avogadro molecular editor project.
 
8
  For more information, see <http://avogadro.openmolecules.net/>
 
9
 
 
10
  Some code is based on Open Babel
 
11
  For more information, see <http://openbabel.sourceforge.net/>
 
12
 
 
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.
 
16
 
 
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
 ***********************************************************************/
 
22
 
 
23
#include "animation.h"
 
24
 
 
25
#include <avogadro/molecule.h>
 
26
#include <avogadro/atom.h>
 
27
#include <avogadro/bond.h>
 
28
#include <openbabel/mol.h>
 
29
#include <Eigen/Core>
 
30
 
 
31
#include <QTimeLine>
 
32
 
 
33
using namespace OpenBabel;
 
34
using Eigen::Vector3d;
 
35
 
 
36
namespace Avogadro {
 
37
 
 
38
  class AnimationPrivate
 
39
  {
 
40
    public:
 
41
      AnimationPrivate() : fps(25), framesSet(false), dynamicBonds(false) {}
 
42
 
 
43
      int fps;
 
44
      bool framesSet;
 
45
      bool dynamicBonds;
 
46
  };
 
47
 
 
48
  Animation::Animation(QObject *parent) : QObject(parent), d(new AnimationPrivate),
 
49
                                          m_molecule(0), m_timeLine(new QTimeLine)
 
50
  {
 
51
    // in chemical animations, each frame should take the same time
 
52
    m_timeLine->setCurveShape(QTimeLine::LinearCurve);
 
53
  }
 
54
 
 
55
  Animation::~Animation()
 
56
  {
 
57
    if (m_timeLine) {
 
58
      delete m_timeLine;
 
59
      m_timeLine = 0;
 
60
    }
 
61
 
 
62
    delete d;
 
63
  }
 
64
 
 
65
  void Animation::setMolecule(Molecule *molecule)
 
66
  {
 
67
    m_molecule = molecule;
 
68
    if (molecule == NULL)
 
69
      return; // we can't save the current conformers
 
70
 
 
71
    if (d->framesSet) {
 
72
      m_originalConformers.clear();
 
73
      for (unsigned int i = 0; i < molecule->numConformers(); ++i) {
 
74
        m_originalConformers.push_back(molecule->conformer(i));
 
75
      }
 
76
    } else {
 
77
      m_timeLine->setFrameRange( 1, m_molecule->numConformers() );
 
78
    }
 
79
  }
 
80
 
 
81
  int Animation::numFrames() const
 
82
  {
 
83
    if (d->framesSet)
 
84
      return m_frames.size();
 
85
    if (m_molecule)
 
86
      return m_molecule->numConformers();
 
87
    return 0;  
 
88
  }
 
89
 
 
90
  int Animation::fps() const
 
91
  {
 
92
    return d->fps;
 
93
  }
 
94
 
 
95
  void Animation::setFps(int fps)
 
96
  {
 
97
    d->fps = fps;
 
98
  }
 
99
 
 
100
  int Animation::loopCount() const
 
101
  {
 
102
    return m_timeLine->loopCount();
 
103
  }
 
104
 
 
105
  void Animation::setLoopCount(int loops)
 
106
  {
 
107
    m_timeLine->setLoopCount(loops);
 
108
  }
 
109
 
 
110
  void Animation::setFrame(int i)
 
111
  {
 
112
    if (i <= 0 || !m_molecule || i > (int)m_molecule->numConformers())
 
113
      return; // nothing to do
 
114
 
 
115
    m_molecule->lock()->lockForWrite();
 
116
    m_molecule->setConformer(i-1); // Frame counting starts from 1
 
117
 
 
118
    if (d->dynamicBonds) {
 
119
      // construct minimal OBMol
 
120
      OpenBabel::OBMol obmol;
 
121
      obmol.BeginModify();
 
122
      foreach(Atom *atom, m_molecule->atoms()) {
 
123
        OpenBabel::OBAtom *a = obmol.NewAtom();
 
124
        OpenBabel::OBAtom obatom = atom->OBAtom();
 
125
        *a = obatom;
 
126
      }
 
127
      obmol.EndModify();
 
128
 
 
129
      // connect the dots
 
130
      obmol.ConnectTheDots();
 
131
 
 
132
      QList<Bond*> bonds(m_molecule->bonds());
 
133
      foreach(Bond *bond, bonds)
 
134
        m_molecule->removeBond(bond->id());
 
135
 
 
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());
 
141
      }
 
142
    }
 
143
    m_molecule->lock()->unlock();
 
144
    m_molecule->update();
 
145
    emit frameChanged(i);
 
146
  }
 
147
 
 
148
  bool Animation::dynamicBonds() const
 
149
  {
 
150
    return d->dynamicBonds;
 
151
  }
 
152
 
 
153
  void Animation::setDynamicBonds(bool enable)
 
154
  {
 
155
    d->dynamicBonds = enable;
 
156
  }
 
157
 
 
158
  void Animation::setFrames(std::vector< std::vector< Eigen::Vector3d> *> frames)
 
159
  {
 
160
    if (frames.size() == 0)
 
161
      return; // nothing to do
 
162
 
 
163
    if (!m_originalConformers.empty())
 
164
      m_originalConformers.clear();
 
165
    if (m_molecule) {
 
166
      for (unsigned int i = 0; i < m_molecule->numConformers(); ++i) {
 
167
        m_originalConformers.push_back(m_molecule->conformer(i));
 
168
      }
 
169
    }
 
170
 
 
171
    d->framesSet = true;
 
172
    m_frames = frames;
 
173
    m_timeLine->setFrameRange(1, numFrames() );
 
174
  }
 
175
 
 
176
  void Animation::stop()
 
177
  {
 
178
    if(!m_molecule)
 
179
      return;
 
180
 
 
181
    m_timeLine->stop();
 
182
    m_timeLine->setCurrentTime(0);
 
183
    disconnect(m_timeLine, SIGNAL(frameChanged(int)),
 
184
            this, SLOT(setFrame(int)));
 
185
 
 
186
    // restore original conformers
 
187
    if (d->framesSet) {
 
188
      m_molecule->lock()->lockForWrite();
 
189
      m_molecule->setAllConformers(m_originalConformers);
 
190
      m_molecule->lock()->unlock();
 
191
    }
 
192
    setFrame(1);
 
193
  }
 
194
 
 
195
  void Animation::start()
 
196
  {
 
197
    if(!m_molecule)
 
198
      return;
 
199
 
 
200
    // set molecule conformers
 
201
    if (d->framesSet) {
 
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();
 
206
    }
 
207
 
 
208
    if (d->fps < 1.0)
 
209
      d->fps = 1.0;
 
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() );
 
215
 
 
216
    connect(m_timeLine, SIGNAL(frameChanged(int)),
 
217
            this, SLOT(setFrame(int)));
 
218
    setFrame(1);
 
219
    m_timeLine->setCurrentTime(0);
 
220
    m_timeLine->start();
 
221
  }
 
222
  
 
223
  void Animation::pause()
 
224
  {
 
225
    m_timeLine->stop();
 
226
  }
 
227
 
 
228
} // end namespace Avogadro