some fixes to the cmake files. It still is not working
[kdeedu-porting.git] / kalzium / libavogadro-kalzium / src / primitive.cpp
blob089bfdccea65c922db6b4909349ae652a6b07ffa
1 /**********************************************************************
2 Primitive - Wrapper class around the OpenBabel classes
4 Copyright (C) 2007 Donald Ephraim Curtis
6 This file is part of the Avogadro molecular editor project.
7 For more information, see <http://avogadro.sourceforge.net/>
9 Avogadro is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 Avogadro is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA.
23 **********************************************************************/
25 #include <config.h>
27 #include <avogadro/primitive.h>
28 #include <eigen/regression.h>
30 #include <QReadWriteLock>
32 using namespace OpenBabel;
34 namespace Avogadro {
36 class PrimitivePrivate {
37 public:
38 PrimitivePrivate() : type(Primitive::OtherType) {};
40 enum Primitive::Type type;
41 QReadWriteLock lock;
44 Primitive::Primitive(QObject *parent) : QObject(parent), d_ptr(new PrimitivePrivate) {}
46 Primitive::Primitive(enum Type type, QObject *parent) : QObject(parent), d_ptr(new PrimitivePrivate)
48 Q_D(Primitive);
49 d->type = type;
52 Primitive::Primitive(PrimitivePrivate &dd, QObject *parent) : QObject(parent), d_ptr(&dd) {}
54 Primitive::Primitive(PrimitivePrivate &dd, enum Type type, QObject *parent) : QObject(parent), d_ptr(&dd)
56 Q_D(Primitive);
57 d->type = type;
60 Primitive::~Primitive()
62 delete d_ptr;
65 enum Primitive::Type Primitive::type() const
67 Q_D(const Primitive);
68 return d->type;
71 QReadWriteLock *Primitive::lock()
73 Q_D(Primitive);
74 return &d->lock;
77 void Primitive::update()
79 emit updated();
82 class MoleculePrivate : public PrimitivePrivate {
83 public:
84 MoleculePrivate() : PrimitivePrivate(), farthestAtom(0), invalidGeomInfo(true) {}
85 mutable Eigen::Vector3d center;
86 mutable Eigen::Vector3d normalVector;
87 mutable double radius;
88 mutable Atom * farthestAtom;
89 mutable bool invalidGeomInfo;
92 Molecule::Molecule(QObject *parent) : Primitive(*new MoleculePrivate, MoleculeType, parent), OpenBabel::OBMol()
94 connect(this, SIGNAL(updated()), this, SLOT(updatePrimitive()));
97 Molecule::Molecule(const Molecule &other) : Primitive(*new MoleculePrivate, MoleculeType, other.parent()), OpenBabel::OBMol(other)
99 connect(this, SIGNAL(updated()), this, SLOT(updatePrimitive()));
102 Molecule::~Molecule()
106 Atom * Molecule::CreateAtom()
108 Atom *atom = new Atom(this);
109 connect(atom, SIGNAL(updated()), this, SLOT(updatePrimitive()));
110 emit primitiveAdded(atom);
111 return(atom);
114 Bond * Molecule::CreateBond()
116 Bond *bond = new Bond(this);
117 connect(bond, SIGNAL(updated()), this, SLOT(updatePrimitive()));
118 emit primitiveAdded(bond);
119 return(bond);
122 Residue * Molecule::CreateResidue()
124 Residue *residue = new Residue(this);
125 connect(residue, SIGNAL(updated()), this, SLOT(updatePrimitive()));
126 emit primitiveAdded(residue);
127 return(residue);
130 void Molecule::DestroyAtom(OpenBabel::OBAtom *obatom)
132 Atom *atom = static_cast<Atom *>(obatom);
133 if(atom) {
134 emit primitiveRemoved(atom);
135 atom->deleteLater();
139 void Molecule::DestroyBond(OpenBabel::OBBond *obbond)
141 Bond *bond = static_cast<Bond *>(obbond);
142 if(bond) {
143 emit primitiveRemoved(bond);
144 bond->deleteLater();
148 void Molecule::DestroyResidue(OpenBabel::OBResidue *obresidue)
150 Residue *residue = static_cast<Residue *>(obresidue);
151 if(residue) {
152 emit primitiveRemoved(residue);
153 residue->deleteLater();
157 void Molecule::updatePrimitive()
159 Q_D(Molecule);
160 Primitive *primitive = qobject_cast<Primitive *>(sender());
161 d->invalidGeomInfo = true;
162 emit primitiveUpdated(primitive);
165 void Molecule::update()
167 Q_D(Molecule);
168 d->invalidGeomInfo = true;
169 emit updated();
172 const Eigen::Vector3d & Molecule::center() const
174 Q_D(const Molecule);
175 if( d->invalidGeomInfo ) computeGeomInfo();
176 return d->center;
179 const Eigen::Vector3d & Molecule::normalVector() const
181 Q_D(const Molecule);
182 if( d->invalidGeomInfo ) computeGeomInfo();
183 return d->normalVector;
186 const double & Molecule::radius() const
188 Q_D(const Molecule);
189 if( d->invalidGeomInfo ) computeGeomInfo();
190 return d->radius;
193 const Atom * Molecule::farthestAtom() const
195 Q_D(const Molecule);
196 if( d->invalidGeomInfo ) computeGeomInfo();
197 return d->farthestAtom;
200 Molecule &Molecule::operator=(const Molecule& other)
202 OpenBabel::OBMol::operator=(other);
203 return *this;
206 Molecule &Molecule::operator+=(const Molecule& other)
208 OpenBabel::OBMol::operator+=(other);
210 return *this;
213 void Molecule::computeGeomInfo() const
215 // MoleculePrivate *d = reinterpret_cast<MoleculePrivate *>(d_ptr);
216 Q_D(const Molecule);
217 d->invalidGeomInfo = true;
218 d->farthestAtom = 0;
219 d->center.loadZero();
220 d->normalVector.loadZero();
221 d->radius = 0.0;
222 if( NumAtoms() != 0 )
224 // compute center
225 std::vector< OpenBabel::OBAtom * >::iterator atom_iterator;
226 for( Atom* atom = (Atom*) const_cast<Molecule*>(this)->BeginAtom(atom_iterator); atom; atom = (Atom *) const_cast<Molecule*>(this)->NextAtom(atom_iterator) )
228 d->center += atom->pos();
230 d->center /= NumAtoms();
232 // compute the normal vector to the molecule's best-fitting plane
233 Eigen::Vector3d * atomPositions = new Eigen::Vector3d[NumAtoms()];
234 int i = 0;
235 for( Atom* atom = (Atom*) const_cast<Molecule*>(this)->BeginAtom(atom_iterator); atom; atom = (Atom *) const_cast<Molecule*>(this)->NextAtom(atom_iterator) )
237 atomPositions[i++] = atom->pos();
239 Eigen::Vector4d planeCoeffs;
240 Eigen::computeFittingHyperplane( NumAtoms(), atomPositions, &planeCoeffs );
241 delete[] atomPositions;
242 d->normalVector = Eigen::Vector3d( planeCoeffs.x(), planeCoeffs.y(), planeCoeffs.z() );
243 d->normalVector.normalize();
245 // compute radius and the farthest atom
246 d->radius = -1.0; // so that ( squaredDistanceToCenter > d->radius ) is true for at least one atom.
247 for( Atom* atom = (Atom*) const_cast<Molecule*>(this)->BeginAtom(atom_iterator); atom; atom = (Atom *) const_cast<Molecule*>(this)->NextAtom(atom_iterator) )
249 double distanceToCenter = (atom->pos() - d->center).norm();
250 if( distanceToCenter > d->radius )
252 d->radius = distanceToCenter;
253 d->farthestAtom = atom;
257 d->invalidGeomInfo = false;
262 #include "primitive.moc"