| [c67518] | 1 | /*
 | 
|---|
 | 2 |  * Project: MoleCuilder
 | 
|---|
 | 3 |  * Description: creates and alters molecular systems
 | 
|---|
 | 4 |  * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 | 
|---|
| [5aaa43] | 5 |  * Copyright (C)  2013 Frederik Heber. All rights reserved.
 | 
|---|
| [94d5ac6] | 6 |  * 
 | 
|---|
 | 7 |  *
 | 
|---|
 | 8 |  *   This file is part of MoleCuilder.
 | 
|---|
 | 9 |  *
 | 
|---|
 | 10 |  *    MoleCuilder is free software: you can redistribute it and/or modify
 | 
|---|
 | 11 |  *    it under the terms of the GNU General Public License as published by
 | 
|---|
 | 12 |  *    the Free Software Foundation, either version 2 of the License, or
 | 
|---|
 | 13 |  *    (at your option) any later version.
 | 
|---|
 | 14 |  *
 | 
|---|
 | 15 |  *    MoleCuilder is distributed in the hope that it will be useful,
 | 
|---|
 | 16 |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 17 |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 18 |  *    GNU General Public License for more details.
 | 
|---|
 | 19 |  *
 | 
|---|
 | 20 |  *    You should have received a copy of the GNU General Public License
 | 
|---|
 | 21 |  *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| [c67518] | 22 |  */
 | 
|---|
 | 23 | 
 | 
|---|
 | 24 | /*
 | 
|---|
 | 25 |  * GLMoleculeObject_molecule.cpp
 | 
|---|
 | 26 |  *
 | 
|---|
 | 27 |  *  Created on: Mar 30, 2012
 | 
|---|
 | 28 |  *      Author: ankele
 | 
|---|
 | 29 |  */
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | // include config.h
 | 
|---|
 | 36 | #ifdef HAVE_CONFIG_H
 | 
|---|
 | 37 | #include <config.h>
 | 
|---|
 | 38 | #endif
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | #include "GLMoleculeObject_molecule.hpp"
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | #include <Qt3D/qglscenenode.h>
 | 
|---|
| [34e7fdb] | 43 | #include <Qt3D/qglbuilder.h>
 | 
|---|
| [c67518] | 44 | 
 | 
|---|
 | 45 | #include "CodePatterns/MemDebug.hpp"
 | 
|---|
 | 46 | 
 | 
|---|
| [6c16a0] | 47 | #include <boost/assign.hpp>
 | 
|---|
 | 48 | 
 | 
|---|
| [c67518] | 49 | #include "CodePatterns/Assert.hpp"
 | 
|---|
 | 50 | #include "CodePatterns/Log.hpp"
 | 
|---|
 | 51 | #include "CodePatterns/Observer/Notification.hpp"
 | 
|---|
| [856d05] | 52 | #include "CodePatterns/Observer/ObserverLog.hpp"
 | 
|---|
| [c67518] | 53 | 
 | 
|---|
 | 54 | #include "Atom/atom.hpp"
 | 
|---|
 | 55 | #include "molecule.hpp"
 | 
|---|
 | 56 | #include "Descriptors/AtomIdDescriptor.hpp"
 | 
|---|
| [704d59] | 57 | #include "Descriptors/MoleculeIdDescriptor.hpp"
 | 
|---|
| [c67518] | 58 | #include "Element/element.hpp"
 | 
|---|
 | 59 | #include "LinearAlgebra/Vector.hpp"
 | 
|---|
| [34e7fdb] | 60 | #include "LinkedCell/PointCloudAdaptor.hpp"
 | 
|---|
 | 61 | #include "LinkedCell/linkedcell.hpp"
 | 
|---|
 | 62 | #include "Tesselation/tesselation.hpp"
 | 
|---|
 | 63 | #include "Tesselation/BoundaryLineSet.hpp"
 | 
|---|
 | 64 | #include "Tesselation/BoundaryTriangleSet.hpp"
 | 
|---|
 | 65 | #include "Tesselation/CandidateForTesselation.hpp"
 | 
|---|
 | 66 | #include "Atom/TesselPoint.hpp"
 | 
|---|
| [c67518] | 67 | #include "World.hpp"
 | 
|---|
 | 68 | 
 | 
|---|
| [6c16a0] | 69 | using namespace boost::assign;
 | 
|---|
 | 70 | 
 | 
|---|
| [8c001a] | 71 | #include "GLMoleculeObject_atom.hpp"
 | 
|---|
 | 72 | 
 | 
|---|
| [6c16a0] | 73 | static Observable::channels_t getAtomsChannels()
 | 
|---|
| [34e7fdb] | 74 | {
 | 
|---|
| [6c16a0] | 75 |   Observable::channels_t channels;
 | 
|---|
 | 76 |   channels += molecule::AtomInserted, molecule::AtomRemoved;
 | 
|---|
 | 77 |   return channels;
 | 
|---|
 | 78 | }
 | 
|---|
| [34e7fdb] | 79 | 
 | 
|---|
| [6c16a0] | 80 | static Observable::channels_t getAllAtomicChangesChannels()
 | 
|---|
 | 81 | {
 | 
|---|
 | 82 |   Observable::channels_t channels;
 | 
|---|
 | 83 |   channels += molecule::AtomInserted, molecule::AtomRemoved, molecule::AtomMoved;
 | 
|---|
 | 84 |   return channels;
 | 
|---|
 | 85 | }
 | 
|---|
| [34e7fdb] | 86 | 
 | 
|---|
| [6c16a0] | 87 | // static instances
 | 
|---|
 | 88 | const Observable::channels_t GLMoleculeObject_molecule::AtomsChannels(getAtomsChannels());
 | 
|---|
 | 89 | const Observable::channels_t GLMoleculeObject_molecule::HullChannels(getAllAtomicChangesChannels());
 | 
|---|
 | 90 | const Observable::channels_t GLMoleculeObject_molecule::BoundingBoxChannels(getAllAtomicChangesChannels());
 | 
|---|
 | 91 | const Observable::channels_t GLMoleculeObject_molecule::IndexChannels(1, molecule::IndexChanged);
 | 
|---|
| [34e7fdb] | 92 | 
 | 
|---|
| [6c16a0] | 93 | static QGLSceneNode *createMoleculeMesh(const QGeometryData &_geo)
 | 
|---|
 | 94 | {
 | 
|---|
| [34e7fdb] | 95 |   // Build a mesh from the geometry.
 | 
|---|
 | 96 |   QGLBuilder builder;
 | 
|---|
| [6c16a0] | 97 |   builder.addTriangles(_geo);
 | 
|---|
| [34e7fdb] | 98 |   QGLSceneNode *mesh = builder.finalizedSceneNode();
 | 
|---|
 | 99 |   return mesh;
 | 
|---|
 | 100 | }
 | 
|---|
 | 101 | 
 | 
|---|
| [6c16a0] | 102 | GLMoleculeObject_molecule::GLMoleculeObject_molecule(QObject *parent, const moleculeId_t _molid) :
 | 
|---|
 | 103 |   GLMoleculeObject((QGLSceneNode *)NULL, parent),
 | 
|---|
 | 104 |   Observer(std::string("GLMoleculeObject_molecule")+toString(_molid)),
 | 
|---|
 | 105 |   owner(NULL),
 | 
|---|
 | 106 |   molref(getMolecule(_molid)),
 | 
|---|
 | 107 |   /* We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
 | 
|---|
 | 108 |    * boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
 | 
|---|
 | 109 |    * the class has not been fully constructed yet. "This" itself seems to be working fine.
 | 
|---|
 | 110 |    */
 | 
|---|
 | 111 |   MolIndexUpdater(
 | 
|---|
 | 112 |       boost::bind(&GLMoleculeObject_molecule::updateIndex, this)
 | 
|---|
 | 113 |       ),
 | 
|---|
 | 114 |   TesselationHullUpdater(
 | 
|---|
 | 115 |       boost::bind(&GLMoleculeObject_molecule::updateTesselationHull, this)
 | 
|---|
 | 116 |       ),
 | 
|---|
 | 117 |   IsSelectedUpdater(
 | 
|---|
 | 118 |       boost::bind(&GLMoleculeObject_molecule::updateIsSelected, this)
 | 
|---|
 | 119 |       ),
 | 
|---|
 | 120 |   BoundingBoxUpdater(
 | 
|---|
 | 121 |       boost::bind(&GLMoleculeObject_molecule::updateBoundingBox, this)
 | 
|---|
 | 122 |       ),
 | 
|---|
 | 123 |   PresentAtomsUpdater(
 | 
|---|
 | 124 |       boost::bind(&GLMoleculeObject_molecule::updateAtoms, this)
 | 
|---|
 | 125 |       ),
 | 
|---|
 | 126 |   MolIndex(
 | 
|---|
 | 127 |       molref,
 | 
|---|
 | 128 |       MolIndexUpdater,
 | 
|---|
 | 129 |       "MoleculeIndex_"+toString(_molid),
 | 
|---|
 | 130 |       _molid,
 | 
|---|
 | 131 |       IndexChannels),
 | 
|---|
 | 132 |   TesselationHull(
 | 
|---|
 | 133 |       molref,
 | 
|---|
 | 134 |       TesselationHullUpdater,
 | 
|---|
 | 135 |       "MoleculeTesselationHull_"+toString(_molid),
 | 
|---|
 | 136 |       HullChannels),
 | 
|---|
 | 137 |   isSelected(
 | 
|---|
 | 138 |       const_cast<const World * const>(World::getPointer()),
 | 
|---|
 | 139 |       IsSelectedUpdater,
 | 
|---|
 | 140 |       "MoleculeBoundingBox_"+toString(_molid),
 | 
|---|
 | 141 |       updateIsSelected(),
 | 
|---|
 | 142 |       BoundingBoxChannels),
 | 
|---|
 | 143 |   BoundingBox(
 | 
|---|
 | 144 |       molref,
 | 
|---|
 | 145 |       BoundingBoxUpdater,
 | 
|---|
 | 146 |       "MoleculeBoundingBox_"+toString(_molid),
 | 
|---|
 | 147 |       updateBoundingBox(),
 | 
|---|
 | 148 |       BoundingBoxChannels),
 | 
|---|
 | 149 |   PresentAtoms(
 | 
|---|
 | 150 |       molref,
 | 
|---|
 | 151 |       PresentAtomsUpdater,
 | 
|---|
 | 152 |       "MoleculeAtoms_"+toString(_molid),
 | 
|---|
 | 153 |       updateAtoms(),
 | 
|---|
 | 154 |       AtomsChannels),
 | 
|---|
| [704d59] | 155 |   hoverAtomId(-1)
 | 
|---|
| [34e7fdb] | 156 | {
 | 
|---|
| [6c16a0] | 157 |   setObjectId(_molid);
 | 
|---|
| [34e7fdb] | 158 |   setMaterial(getMaterial(1));
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |   // initially, atoms and bonds should be visible
 | 
|---|
 | 161 |   m_visible = false;
 | 
|---|
 | 162 | 
 | 
|---|
| [2b596f] | 163 |   connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
 | 
|---|
 | 164 |   connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
 | 
|---|
| [6c16a0] | 165 |   connect (this, SIGNAL(TesselationHullChanged()), this, SLOT(resetTesselationHull()), Qt::QueuedConnection);
 | 
|---|
 | 166 |   connect (this, SIGNAL(BoundingBoxChanged()), this, SLOT(resetBoundingBox()), Qt::QueuedConnection);
 | 
|---|
 | 167 |   connect (this, SIGNAL(IsSelectedChanged()), this, SLOT(resetIsSelected()), Qt::QueuedConnection);
 | 
|---|
 | 168 |   connect (this, SIGNAL(IdChanged()), this, SLOT(resetIndex()), Qt::QueuedConnection);
 | 
|---|
 | 169 |   connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(atomInserted(const atomId_t)), Qt::QueuedConnection);
 | 
|---|
 | 170 |   connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
 | 
|---|
 | 171 |   connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
 | 
|---|
 | 172 |   connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(atomRemoved(const atomId_t)), Qt::QueuedConnection);
 | 
|---|
| [9a7ef9] | 173 | 
 | 
|---|
 | 174 |   connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
 | 
|---|
| [34e7fdb] | 175 | }
 | 
|---|
 | 176 | 
 | 
|---|
| [6c16a0] | 177 | GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const moleculeId_t _molid) :
 | 
|---|
| [bca99d] | 178 |   GLMoleculeObject(mesh, parent),
 | 
|---|
| [6c16a0] | 179 |   Observer(std::string("GLMoleculeObject_molecule")+toString(_molid)),
 | 
|---|
 | 180 |   owner(NULL),
 | 
|---|
 | 181 |   molref(getMolecule(_molid)),
 | 
|---|
 | 182 |   /* We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
 | 
|---|
 | 183 |    * boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
 | 
|---|
 | 184 |    * the class has not been fully constructed yet. "This" itself seems to be working fine.
 | 
|---|
 | 185 |    */
 | 
|---|
 | 186 |   MolIndexUpdater(
 | 
|---|
 | 187 |       boost::bind(&GLMoleculeObject_molecule::updateIndex, this)
 | 
|---|
 | 188 |       ),
 | 
|---|
 | 189 |   TesselationHullUpdater(
 | 
|---|
 | 190 |       boost::bind(&GLMoleculeObject_molecule::updateTesselationHull, this)
 | 
|---|
 | 191 |       ),
 | 
|---|
 | 192 |   IsSelectedUpdater(
 | 
|---|
 | 193 |       boost::bind(&GLMoleculeObject_molecule::updateIsSelected, this)
 | 
|---|
 | 194 |       ),
 | 
|---|
 | 195 |   BoundingBoxUpdater(
 | 
|---|
 | 196 |       boost::bind(&GLMoleculeObject_molecule::updateBoundingBox, this)
 | 
|---|
 | 197 |       ),
 | 
|---|
 | 198 |   PresentAtomsUpdater(
 | 
|---|
 | 199 |       boost::bind(&GLMoleculeObject_molecule::updateAtoms, this)
 | 
|---|
 | 200 |       ),
 | 
|---|
 | 201 |   MolIndex(
 | 
|---|
 | 202 |       molref,
 | 
|---|
 | 203 |       MolIndexUpdater,
 | 
|---|
 | 204 |       "MoleculeIndex_"+toString(_molid),
 | 
|---|
 | 205 |       _molid,
 | 
|---|
 | 206 |       IndexChannels),
 | 
|---|
 | 207 |   TesselationHull(
 | 
|---|
 | 208 |       molref,
 | 
|---|
 | 209 |       TesselationHullUpdater,
 | 
|---|
 | 210 |       "MoleculeTesselationHull_"+toString(_molid),
 | 
|---|
 | 211 |       HullChannels),
 | 
|---|
 | 212 |   isSelected(
 | 
|---|
 | 213 |       const_cast<const World * const>(World::getPointer()),
 | 
|---|
 | 214 |       IsSelectedUpdater,
 | 
|---|
 | 215 |       "MoleculeBoundingBox_"+toString(_molid),
 | 
|---|
 | 216 |       updateIsSelected(),
 | 
|---|
 | 217 |       BoundingBoxChannels),
 | 
|---|
 | 218 |   BoundingBox(
 | 
|---|
 | 219 |       molref,
 | 
|---|
 | 220 |       BoundingBoxUpdater,
 | 
|---|
 | 221 |       "MoleculeBoundingBox_"+toString(_molid),
 | 
|---|
 | 222 |       updateBoundingBox(),
 | 
|---|
 | 223 |       BoundingBoxChannels),
 | 
|---|
 | 224 |   PresentAtoms(
 | 
|---|
 | 225 |       molref,
 | 
|---|
 | 226 |       PresentAtomsUpdater,
 | 
|---|
 | 227 |       "MoleculeAtoms_"+toString(_molid),
 | 
|---|
 | 228 |       atoms_t(),
 | 
|---|
 | 229 |       AtomsChannels),
 | 
|---|
| [704d59] | 230 |   hoverAtomId(-1)
 | 
|---|
| [c67518] | 231 | {
 | 
|---|
| [6c16a0] | 232 |   setObjectId(_molid);
 | 
|---|
| [3b229e] | 233 |   setMaterial(getMaterial(1));
 | 
|---|
| [8c001a] | 234 | 
 | 
|---|
| [739ee9] | 235 |   // initially, atoms and bonds should be visible
 | 
|---|
 | 236 |   m_visible = false;
 | 
|---|
 | 237 | 
 | 
|---|
| [2b596f] | 238 |   connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
 | 
|---|
 | 239 |   connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
 | 
|---|
| [6c16a0] | 240 |   connect (this, SIGNAL(TesselationHullChanged()), this, SLOT(resetTesselationHull()), Qt::QueuedConnection);
 | 
|---|
 | 241 |   connect (this, SIGNAL(BoundingBoxChanged()), this, SLOT(resetBoundingBox()), Qt::QueuedConnection);
 | 
|---|
 | 242 |   connect (this, SIGNAL(IsSelectedChanged()), this, SLOT(resetIsSelected()), Qt::QueuedConnection);
 | 
|---|
 | 243 |   connect (this, SIGNAL(IdChanged()), this, SLOT(resetIndex()), Qt::QueuedConnection);
 | 
|---|
 | 244 |   connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(atomInserted(const atomId_t)), Qt::QueuedConnection);
 | 
|---|
 | 245 |   connect (this, SIGNAL(AtomInserted(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
 | 
|---|
 | 246 |   connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(resetAtoms()), Qt::QueuedConnection);
 | 
|---|
 | 247 |   connect (this, SIGNAL(AtomRemoved(const atomId_t)), this, SLOT(atomRemoved(const atomId_t)), Qt::QueuedConnection);
 | 
|---|
| [9a7ef9] | 248 | 
 | 
|---|
 | 249 |   connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
 | 
|---|
| [c67518] | 250 | }
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
 | 
|---|
 | 253 | {
 | 
|---|
| [6c16a0] | 254 |   deactivateObserver();
 | 
|---|
 | 255 | }
 | 
|---|
 | 256 | 
 | 
|---|
 | 257 | void GLMoleculeObject_molecule::deactivateObserver()
 | 
|---|
 | 258 | {
 | 
|---|
 | 259 |   if (owner != NULL) {
 | 
|---|
 | 260 |     owner->signOff(this, molecule::AtomInserted);
 | 
|---|
 | 261 |     owner->signOff(this, molecule::AtomRemoved);
 | 
|---|
 | 262 |     owner->signOff(this, molecule::AtomMoved);
 | 
|---|
 | 263 |     owner->signOff(this, molecule::IndexChanged);
 | 
|---|
 | 264 |     /*_atom->signOff(this, AtomObservable::IndexChanged);
 | 
|---|
 | 265 |     _atom->signOff(this, AtomObservable::PositionChanged);
 | 
|---|
 | 266 |     _atom->signOff(this, AtomObservable::ElementChanged);
 | 
|---|
 | 267 |     _atom->signOff(this, AtomObservable::BondsAdded);*/
 | 
|---|
 | 268 |     World::getInstance().signOff(this, World::SelectionChanged);
 | 
|---|
 | 269 |     owner = NULL;
 | 
|---|
| [34e7fdb] | 270 |   }
 | 
|---|
| [c67518] | 271 | }
 | 
|---|
 | 272 | 
 | 
|---|
| [73b13c] | 273 | void GLMoleculeObject_molecule::activateObserver()
 | 
|---|
 | 274 | {
 | 
|---|
 | 275 |   // sign on as observer (obtain non-const instance before)
 | 
|---|
| [6c16a0] | 276 |   const molecule * const _molecule = getMolecule(MolIndex.get());
 | 
|---|
| [73b13c] | 277 |   if (_molecule != NULL) {
 | 
|---|
| [6c16a0] | 278 |     owner = static_cast<const Observable *>(_molecule);
 | 
|---|
 | 279 |     owner->signOn(this, molecule::AtomInserted);
 | 
|---|
 | 280 |     owner->signOn(this, molecule::AtomRemoved);
 | 
|---|
 | 281 |     owner->signOn(this, molecule::AtomMoved);
 | 
|---|
 | 282 |     owner->signOn(this, molecule::IndexChanged);
 | 
|---|
 | 283 |     /*molref->signOn(this, AtomObservable::IndexChanged);
 | 
|---|
 | 284 |     molref->signOn(this, AtomObservable::PositionChanged);
 | 
|---|
 | 285 |     molref->signOn(this, AtomObservable::ElementChanged);
 | 
|---|
 | 286 |     molref->signOn(this, AtomObservable::BondsAdded);*/
 | 
|---|
 | 287 |     World::getInstance().signOn(this, World::SelectionChanged);
 | 
|---|
| [73b13c] | 288 |   } else {
 | 
|---|
| [6c16a0] | 289 |     ELOG(1, "GLMoleculeObject_molecule() - added null object for not present mol id " << MolIndex.get());
 | 
|---|
| [73b13c] | 290 |   }
 | 
|---|
| [6c16a0] | 291 | 
 | 
|---|
| [73b13c] | 292 | }
 | 
|---|
 | 293 | 
 | 
|---|
| [8c001a] | 294 | void GLMoleculeObject_molecule::addAtomBonds(
 | 
|---|
 | 295 |     const bond::ptr &_bond,
 | 
|---|
 | 296 |     const GLMoleculeObject_bond::SideOfBond _side
 | 
|---|
 | 297 |     )
 | 
|---|
 | 298 | {
 | 
|---|
 | 299 |   bool bond_present = false;
 | 
|---|
 | 300 |   const BondIds ids = getBondIds(_bond, _side);
 | 
|---|
 | 301 |   // check whether bond is not present already
 | 
|---|
 | 302 |   bond_present = BondsinSceneMap.count(ids);
 | 
|---|
 | 303 |   if (!bond_present)
 | 
|---|
| [6c16a0] | 304 |     bondInserted(ids.first, ids.second, _side);
 | 
|---|
| [8c001a] | 305 |   else {
 | 
|---|
 | 306 |     BondsinSceneMap[ids]->resetPosition();
 | 
|---|
 | 307 |     BondsinSceneMap[ids]->resetWidth();
 | 
|---|
 | 308 |   }
 | 
|---|
 | 309 | }
 | 
|---|
 | 310 | 
 | 
|---|
 | 311 | void GLMoleculeObject_molecule::addAtomBonds(
 | 
|---|
 | 312 |     const atom *_atom)
 | 
|---|
 | 313 | {
 | 
|---|
 | 314 |   const bool atom_present = AtomsinSceneMap.count(_atom->getId());
 | 
|---|
 | 315 |   const BondList &bondlist = _atom->getListOfBonds();
 | 
|---|
 | 316 |   for (BondList::const_iterator bonditer = bondlist.begin();
 | 
|---|
 | 317 |       (bonditer != bondlist.end()) && atom_present;
 | 
|---|
 | 318 |       ++bonditer) {
 | 
|---|
 | 319 |     const bond::ptr _bond = *bonditer;
 | 
|---|
 | 320 |     // check if OtherAtom's sphere is already present
 | 
|---|
 | 321 |     const atom *OtherAtom = _bond->GetOtherAtom(_atom);
 | 
|---|
 | 322 |     const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
 | 
|---|
 | 323 |     if (otheratom_present && atom_present) {
 | 
|---|
 | 324 |       const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
 | 
|---|
 | 325 |           GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
 | 
|---|
 | 326 |       const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
 | 
|---|
 | 327 |           GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
 | 
|---|
 | 328 |       addAtomBonds(_bond, side);
 | 
|---|
 | 329 |       addAtomBonds(_bond, otherside);
 | 
|---|
 | 330 |     }
 | 
|---|
 | 331 |   }
 | 
|---|
 | 332 | }
 | 
|---|
 | 333 | 
 | 
|---|
| [6c16a0] | 334 | QGeometryData GLMoleculeObject_molecule::updateTesselationHull() const
 | 
|---|
 | 335 | {
 | 
|---|
 | 336 |   QGeometryData geo;
 | 
|---|
 | 337 | 
 | 
|---|
 | 338 |   const molecule * const molref = getMolecule(MolIndex.get());
 | 
|---|
 | 339 |   if (molref == NULL) {
 | 
|---|
 | 340 |     ELOG(1, "Could not createMoleculeMesh, molecule with id " << MolIndex.get() << " already gone.");
 | 
|---|
 | 341 |     return geo;
 | 
|---|
 | 342 |   }
 | 
|---|
 | 343 |   double minradius = 2.; // TODO: set to maximum bond length value
 | 
|---|
 | 344 |   LOG(3, "DEBUG: Molecule fits into sphere of radius " << minradius);
 | 
|---|
 | 345 |   // check minimum bond radius in molecule
 | 
|---|
 | 346 |   double minlength = std::numeric_limits<double>::max();
 | 
|---|
 | 347 |   for (molecule::const_iterator iter = molref->begin();
 | 
|---|
 | 348 |       iter != molref->end(); ++iter) {
 | 
|---|
 | 349 |     const BondList &ListOfBonds = (*iter)->getListOfBonds();
 | 
|---|
 | 350 |     for (BondList::const_iterator bonditer = ListOfBonds.begin();
 | 
|---|
 | 351 |          bonditer != ListOfBonds.end(); ++bonditer) {
 | 
|---|
 | 352 |       const double bond_distance = (*bonditer)->GetDistance();
 | 
|---|
 | 353 |       minlength = std::min(bond_distance, minlength);
 | 
|---|
 | 354 |     }
 | 
|---|
 | 355 |   }
 | 
|---|
 | 356 |   minradius = std::max( std::max(minradius, minlength), 1.);
 | 
|---|
 | 357 | 
 | 
|---|
 | 358 |   // we need at least three points for tesselation
 | 
|---|
 | 359 |   if (molref->getAtomCount() >= 3) {
 | 
|---|
 | 360 |     // Tesselate the points.
 | 
|---|
 | 361 |     Tesselation T;
 | 
|---|
 | 362 |     PointCloudAdaptor<molecule> cloud(const_cast<molecule *>(molref), molref->getName());
 | 
|---|
 | 363 |     T(cloud, minradius);
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 |     // Fill the points into a Qt geometry.
 | 
|---|
 | 366 |     LinkedCell_deprecated LinkedList(cloud, minradius);
 | 
|---|
 | 367 |     std::map<int, int> indices;
 | 
|---|
 | 368 |     std::map<int, Vector> normals;
 | 
|---|
 | 369 |     int index = 0;
 | 
|---|
 | 370 |     for (PointMap::const_iterator piter = T.PointsOnBoundary.begin();
 | 
|---|
 | 371 |         piter != T.PointsOnBoundary.end(); ++piter) {
 | 
|---|
 | 372 |       const Vector &point = piter->second->getPosition();
 | 
|---|
 | 373 |       // add data to the primitive
 | 
|---|
 | 374 |       geo.appendVertex(QVector3D(point[0], point[1], point[2]));
 | 
|---|
 | 375 |       Vector normalvector;
 | 
|---|
 | 376 |       for (LineMap::const_iterator lineiter = piter->second->lines.begin();
 | 
|---|
 | 377 |           lineiter != piter->second->lines.end(); ++lineiter)
 | 
|---|
 | 378 |         for (TriangleMap::const_iterator triangleiter = lineiter->second->triangles.begin();
 | 
|---|
 | 379 |             triangleiter != lineiter->second->triangles.end(); ++triangleiter)
 | 
|---|
 | 380 |           normalvector +=
 | 
|---|
 | 381 |               triangleiter->second->NormalVector;
 | 
|---|
 | 382 |       normalvector.Normalize();
 | 
|---|
 | 383 |       geo.appendNormal(QVector3D(normalvector[0], normalvector[1], normalvector[2]));
 | 
|---|
 | 384 |       geo.appendColor(QColor(1, 1, 1, 1));
 | 
|---|
 | 385 |       geo.appendTexCoord(QVector2D(0, 0));
 | 
|---|
 | 386 |       indices.insert( std::make_pair( piter->second->getNr(), index++));
 | 
|---|
 | 387 |     }
 | 
|---|
 | 388 | 
 | 
|---|
 | 389 |     // Fill the tesselated triangles into the geometry.
 | 
|---|
 | 390 |     for (TriangleMap::const_iterator runner = T.TrianglesOnBoundary.begin();
 | 
|---|
 | 391 |         runner != T.TrianglesOnBoundary.end(); runner++) {
 | 
|---|
 | 392 |       int v[3];
 | 
|---|
 | 393 |       for (size_t i=0; i<3; ++i)
 | 
|---|
 | 394 |         v[i] = runner->second->endpoints[i]->getNr();
 | 
|---|
 | 395 | 
 | 
|---|
 | 396 |       // Sort the vertices so the triangle is clockwise (relative to the normal vector).
 | 
|---|
 | 397 |       Vector cross = T.PointsOnBoundary[v[1]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition();
 | 
|---|
 | 398 |       cross.VectorProduct(T.PointsOnBoundary[v[2]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition());
 | 
|---|
 | 399 |       if (cross.ScalarProduct(runner->second->NormalVector) > 0)
 | 
|---|
 | 400 |         geo.appendIndices(indices[v[0]], indices[v[1]], indices[v[2]]);
 | 
|---|
 | 401 |       else
 | 
|---|
 | 402 |         geo.appendIndices(indices[v[0]], indices[v[2]], indices[v[1]]);
 | 
|---|
 | 403 |     }
 | 
|---|
 | 404 |   }
 | 
|---|
 | 405 | 
 | 
|---|
 | 406 |   return geo;
 | 
|---|
 | 407 | }
 | 
|---|
 | 408 | 
 | 
|---|
 | 409 | bool GLMoleculeObject_molecule::updateIsSelected() const
 | 
|---|
 | 410 | {
 | 
|---|
 | 411 |   return const_cast<const World &>(World::getInstance()).isMoleculeSelected(MolIndex.get());
 | 
|---|
 | 412 | }
 | 
|---|
 | 413 | 
 | 
|---|
 | 414 | GLMoleculeObject_molecule::BoundingBoxInfo GLMoleculeObject_molecule::updateBoundingBox() const
 | 
|---|
 | 415 | {
 | 
|---|
 | 416 |   BoundingBoxInfo info;
 | 
|---|
 | 417 |   const molecule * const _molecule = getMolecule(MolIndex.get());
 | 
|---|
 | 418 |   if (_molecule != NULL) {
 | 
|---|
 | 419 |     Shape shape = _molecule->getBoundingSphere();
 | 
|---|
 | 420 |     info.position = shape.getCenter();
 | 
|---|
 | 421 |     info.radius = shape.getRadius();
 | 
|---|
 | 422 |   } else
 | 
|---|
 | 423 |     ELOG(2, "GLMoleculeObject_molecule cannot updateBoundingBox, molecule with "
 | 
|---|
 | 424 |         << MolIndex.get() << " has disappeared.");
 | 
|---|
 | 425 |   return info;
 | 
|---|
 | 426 | }
 | 
|---|
 | 427 | 
 | 
|---|
 | 428 | GLMoleculeObject_molecule::atoms_t GLMoleculeObject_molecule::updateAtoms()
 | 
|---|
 | 429 | {
 | 
|---|
 | 430 |   const molecule * const mol = getMolecule(MolIndex.get());
 | 
|---|
| [54bdaa] | 431 |   if (mol != NULL) {
 | 
|---|
 | 432 |     const atomId_t id = mol->lastChangedAtomId();
 | 
|---|
 | 433 |     if (mol->containsAtom(id))
 | 
|---|
 | 434 |       DisplayedAtoms.insert(id);
 | 
|---|
 | 435 |     else
 | 
|---|
 | 436 |       DisplayedAtoms.erase(id);
 | 
|---|
 | 437 |   }
 | 
|---|
| [6c16a0] | 438 |   return DisplayedAtoms;
 | 
|---|
 | 439 | }
 | 
|---|
 | 440 | 
 | 
|---|
 | 441 | moleculeId_t GLMoleculeObject_molecule::updateIndex() const
 | 
|---|
| [d6203a] | 442 | {
 | 
|---|
| [54bdaa] | 443 |   return const_cast<const World &>(World::getInstance()).lastChangedMolId();
 | 
|---|
| [6c16a0] | 444 | }
 | 
|---|
 | 445 | 
 | 
|---|
 | 446 | void GLMoleculeObject_molecule::resetTesselationHull()
 | 
|---|
 | 447 | {
 | 
|---|
 | 448 |   if (!TesselationHull.isValid())
 | 
|---|
 | 449 |     updateMesh(createMoleculeMesh(*TesselationHull));
 | 
|---|
 | 450 | }
 | 
|---|
 | 451 | 
 | 
|---|
 | 452 | void GLMoleculeObject_molecule::resetIsSelected()
 | 
|---|
 | 453 | {
 | 
|---|
 | 454 |   setSelected(isSelected.get());
 | 
|---|
 | 455 | }
 | 
|---|
 | 456 | 
 | 
|---|
 | 457 | void GLMoleculeObject_molecule::resetBoundingBox()
 | 
|---|
 | 458 | {
 | 
|---|
 | 459 |   BoundingBoxInfo info = BoundingBox.get();
 | 
|---|
 | 460 |   setPosition(QVector3D(info.position[0], info.position[1], info.position[2]));
 | 
|---|
 | 461 |   setScale(info.radius + 0.3); // getBoundingSphere() only sees atoms as points, so make the box a bit bigger
 | 
|---|
 | 462 | }
 | 
|---|
 | 463 | 
 | 
|---|
 | 464 | void GLMoleculeObject_molecule::resetAtoms()
 | 
|---|
 | 465 | {
 | 
|---|
 | 466 |   const atoms_t atoms = PresentAtoms.get();
 | 
|---|
 | 467 |   std::vector<atomId_t> InsertedAtoms;
 | 
|---|
 | 468 |   std::vector<atomId_t> RemovedAtoms;
 | 
|---|
 | 469 |   // obtain all newly inserted and removed atoms
 | 
|---|
 | 470 |   std::set_difference(
 | 
|---|
 | 471 |       atoms.begin(), atoms.end(),
 | 
|---|
 | 472 |       DisplayedAtoms.begin(), DisplayedAtoms.end(),
 | 
|---|
 | 473 |       std::back_inserter(InsertedAtoms));
 | 
|---|
 | 474 |   std::set_difference(
 | 
|---|
 | 475 |       DisplayedAtoms.begin(), DisplayedAtoms.end(),
 | 
|---|
 | 476 |       atoms.begin(), atoms.end(),
 | 
|---|
 | 477 |       std::back_inserter(RemovedAtoms));
 | 
|---|
 | 478 |   // remove the atoms
 | 
|---|
 | 479 |   std::for_each(RemovedAtoms.begin(), RemovedAtoms.end(),
 | 
|---|
 | 480 |       boost::bind(&GLMoleculeObject_molecule::atomRemoved, this, _1));
 | 
|---|
 | 481 |   // insert the atoms
 | 
|---|
 | 482 |   std::for_each(InsertedAtoms.begin(), InsertedAtoms.end(),
 | 
|---|
 | 483 |       boost::bind(&GLMoleculeObject_molecule::atomInserted, this, _1));
 | 
|---|
 | 484 | 
 | 
|---|
 | 485 |   emit changed();
 | 
|---|
 | 486 | }
 | 
|---|
 | 487 | 
 | 
|---|
 | 488 | void GLMoleculeObject_molecule::resetIndex()
 | 
|---|
 | 489 | {
 | 
|---|
 | 490 |   const atomId_t newId = MolIndex.get();
 | 
|---|
 | 491 |   const size_t oldId = objectId();
 | 
|---|
 | 492 |   ASSERT( newId != oldId,
 | 
|---|
 | 493 |       "GLMoleculeObject_molecule::resetIndex() - index "+toString(newId)+" did not change.");
 | 
|---|
 | 494 |   LOG(4, "INFO: GLMoleculeObject_molecule: new index is "+toString(newId)+".");
 | 
|---|
 | 495 |   setObjectId(newId);
 | 
|---|
 | 496 | 
 | 
|---|
 | 497 |   emit indexChanged(this, oldId, newId);
 | 
|---|
| [d6203a] | 498 | }
 | 
|---|
 | 499 | 
 | 
|---|
| [c67518] | 500 | void GLMoleculeObject_molecule::update(Observable *publisher)
 | 
|---|
 | 501 | {
 | 
|---|
 | 502 | #ifdef LOG_OBSERVER
 | 
|---|
| [a2a2f7] | 503 |   const molecule *_mol = static_cast<molecule *>(publisher);
 | 
|---|
 | 504 |   observerLog().addMessage() << "++ Update of Observer " << observerLog().getName(static_cast<Observer *>(this)) << " from molecule "+toString(_mol->getId())+".";
 | 
|---|
| [c67518] | 505 | #endif
 | 
|---|
 | 506 | }
 | 
|---|
 | 507 | 
 | 
|---|
 | 508 | void GLMoleculeObject_molecule::subjectKilled(Observable *publisher)
 | 
|---|
| [34e7fdb] | 509 | {
 | 
|---|
| [6c16a0] | 510 |   deactivateObserver();
 | 
|---|
| [34e7fdb] | 511 | }
 | 
|---|
| [c67518] | 512 | 
 | 
|---|
 | 513 | void GLMoleculeObject_molecule::recieveNotification(Observable *publisher, Notification_ptr notification)
 | 
|---|
 | 514 | {
 | 
|---|
| [6c16a0] | 515 |   const molecule * const _molecule = getMolecule(MolIndex.get());
 | 
|---|
| [cc2976] | 516 |   // when molecule is NULL we will soon get destroyed anyway
 | 
|---|
 | 517 |   if (_molecule == NULL)
 | 
|---|
 | 518 |     return;
 | 
|---|
| [c67518] | 519 |   if (publisher == dynamic_cast<const Observable*>(_molecule)){
 | 
|---|
 | 520 |     // notofication from atom
 | 
|---|
 | 521 | #ifdef LOG_OBSERVER
 | 
|---|
| [708277] | 522 |     observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
 | 
|---|
| [c67518] | 523 |           << " received notification from molecule " << _molecule->getId() << " for channel "
 | 
|---|
 | 524 |           << notification->getChannelNo() << ".";
 | 
|---|
 | 525 | #endif
 | 
|---|
| [8c001a] | 526 |     switch (notification->getChannelNo()) {
 | 
|---|
 | 527 |       case molecule::AtomInserted:
 | 
|---|
 | 528 |       {
 | 
|---|
| [54bdaa] | 529 |         const atomId_t _id = _molecule->lastChangedAtomId();
 | 
|---|
| [8c001a] | 530 |   #ifdef LOG_OBSERVER
 | 
|---|
 | 531 |         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
 | 
|---|
 | 532 |   #endif
 | 
|---|
| [6c16a0] | 533 |         emit AtomInserted(_id);
 | 
|---|
 | 534 |         emit TesselationHullChanged();
 | 
|---|
 | 535 |         emit BoundingBoxChanged();
 | 
|---|
| [8c001a] | 536 |         break;
 | 
|---|
 | 537 |       }
 | 
|---|
 | 538 |       case World::AtomRemoved:
 | 
|---|
 | 539 |       {
 | 
|---|
| [54bdaa] | 540 |         const atomId_t _id = _molecule->lastChangedAtomId();
 | 
|---|
| [8c001a] | 541 |   #ifdef LOG_OBSERVER
 | 
|---|
 | 542 |         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been removed.";
 | 
|---|
 | 543 |   #endif
 | 
|---|
| [6c16a0] | 544 |         emit AtomRemoved(_id);
 | 
|---|
 | 545 |         emit TesselationHullChanged();
 | 
|---|
 | 546 |         emit BoundingBoxChanged();
 | 
|---|
| [8c001a] | 547 |         break;
 | 
|---|
 | 548 |       }
 | 
|---|
| [7b5984] | 549 |       case molecule::AtomMoved:
 | 
|---|
 | 550 |       {
 | 
|---|
 | 551 |   #ifdef LOG_OBSERVER
 | 
|---|
| [54bdaa] | 552 |         const atomId_t _id = _molecule->lastChangedAtomId();
 | 
|---|
| [7b5984] | 553 |         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
 | 
|---|
 | 554 |   #endif
 | 
|---|
| [6c16a0] | 555 |         emit TesselationHullChanged();
 | 
|---|
 | 556 |         emit BoundingBoxChanged();
 | 
|---|
 | 557 |         break;
 | 
|---|
 | 558 |       }
 | 
|---|
 | 559 |       case molecule::IndexChanged:
 | 
|---|
 | 560 |       {
 | 
|---|
 | 561 |   #ifdef LOG_OBSERVER
 | 
|---|
| [54bdaa] | 562 |         const atomId_t _id = _molecule->lastChangedAtomId();
 | 
|---|
| [6c16a0] | 563 |         observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+"'s index has changed.";
 | 
|---|
 | 564 |   #endif
 | 
|---|
 | 565 |         emit IdChanged();
 | 
|---|
| [7b5984] | 566 |         break;
 | 
|---|
 | 567 |       }
 | 
|---|
| [8c001a] | 568 |       default:
 | 
|---|
 | 569 |         break;
 | 
|---|
 | 570 |     }
 | 
|---|
| [c67518] | 571 |   }else{
 | 
|---|
 | 572 |     // notification from world
 | 
|---|
 | 573 | #ifdef LOG_OBSERVER
 | 
|---|
| [708277] | 574 |     observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
 | 
|---|
| [c67518] | 575 |           << " received notification from world for channel "
 | 
|---|
 | 576 |           << notification->getChannelNo() << ".";
 | 
|---|
 | 577 | #endif
 | 
|---|
 | 578 |     switch (notification->getChannelNo()) {
 | 
|---|
 | 579 |       case World::SelectionChanged:
 | 
|---|
| [6c16a0] | 580 |         emit IsSelectedChanged();
 | 
|---|
| [c67518] | 581 |         break;
 | 
|---|
 | 582 |       default:
 | 
|---|
 | 583 |         break;
 | 
|---|
 | 584 |     }
 | 
|---|
 | 585 |   }
 | 
|---|
 | 586 | }
 | 
|---|
 | 587 | 
 | 
|---|
| [8c001a] | 588 | void GLMoleculeObject_molecule::initialize(QGLView *view, QGLPainter *painter)
 | 
|---|
 | 589 | {
 | 
|---|
 | 590 |   // Initialize all of the mesh objects that we have as children.
 | 
|---|
| [2b596f] | 591 |   if (m_visible) {
 | 
|---|
 | 592 |     GLMoleculeObject::initialize(view, painter);
 | 
|---|
 | 593 |   } else {
 | 
|---|
| [8c001a] | 594 |    foreach (QObject *obj, children()) {
 | 
|---|
 | 595 |      GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
 | 
|---|
 | 596 |        if (meshobj)
 | 
|---|
 | 597 |          meshobj->initialize(view, painter);
 | 
|---|
 | 598 |    }
 | 
|---|
| [2b596f] | 599 |   }
 | 
|---|
| [8c001a] | 600 | }
 | 
|---|
 | 601 | 
 | 
|---|
 | 602 | void GLMoleculeObject_molecule::draw(QGLPainter *painter, const QVector4D &cameraPlane)
 | 
|---|
 | 603 | {
 | 
|---|
| [739ee9] | 604 |   // draw either molecule's mesh or all atoms and bonds
 | 
|---|
 | 605 |   if (m_visible) {
 | 
|---|
| [6c16a0] | 606 |     resetTesselationHull();
 | 
|---|
| [7b5984] | 607 | 
 | 
|---|
| [34e7fdb] | 608 |     painter->modelViewMatrix().push();
 | 
|---|
 | 609 | 
 | 
|---|
 | 610 |     // Apply the material and effect to the painter.
 | 
|---|
 | 611 |     QGLMaterial *material;
 | 
|---|
 | 612 |     if (m_hovering)
 | 
|---|
 | 613 |         material = m_hoverMaterial;
 | 
|---|
 | 614 |     else if (m_selected)
 | 
|---|
 | 615 |         material = m_selectionMaterial;
 | 
|---|
 | 616 |     else
 | 
|---|
 | 617 |         material = m_material;
 | 
|---|
 | 618 | 
 | 
|---|
 | 619 |     ASSERT(material, "GLMoleculeObject::draw: chosen material is NULL");
 | 
|---|
 | 620 | 
 | 
|---|
 | 621 |     painter->setColor(material->diffuseColor());
 | 
|---|
 | 622 |     painter->setFaceMaterial(QGL::AllFaces, material);
 | 
|---|
 | 623 |     if (m_effect)
 | 
|---|
 | 624 |         painter->setUserEffect(m_effect);
 | 
|---|
 | 625 |     else
 | 
|---|
 | 626 |         painter->setStandardEffect(QGL::LitMaterial);
 | 
|---|
 | 627 | 
 | 
|---|
 | 628 |     // Mark the object for object picking purposes.
 | 
|---|
 | 629 |     int prevObjectId = painter->objectPickId();
 | 
|---|
 | 630 |     if (m_objectId != -1)
 | 
|---|
 | 631 |         painter->setObjectPickId(m_objectId);
 | 
|---|
 | 632 | 
 | 
|---|
 | 633 |     m_mesh[0]->draw(painter);
 | 
|---|
 | 634 | 
 | 
|---|
 | 635 |     // Turn off the user effect, if present.
 | 
|---|
 | 636 |     if (m_effect)
 | 
|---|
 | 637 |         painter->setStandardEffect(QGL::LitMaterial);
 | 
|---|
 | 638 | 
 | 
|---|
 | 639 |     // Revert to the previous object identifier.
 | 
|---|
 | 640 |     painter->setObjectPickId(prevObjectId);
 | 
|---|
 | 641 | 
 | 
|---|
 | 642 |     // Restore the modelview matrix.
 | 
|---|
 | 643 |     painter->modelViewMatrix().pop();
 | 
|---|
 | 644 | 
 | 
|---|
 | 645 |     //    GLMoleculeObject::draw(painter, cameraPlane);
 | 
|---|
| [739ee9] | 646 |   } else {
 | 
|---|
 | 647 |     // Draw all of the mesh objects that we have as children.
 | 
|---|
 | 648 |     foreach (QObject *obj, children()) {
 | 
|---|
 | 649 |       GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
 | 
|---|
 | 650 |       if (meshobj)
 | 
|---|
 | 651 |         meshobj->draw(painter, cameraPlane);
 | 
|---|
 | 652 |     }
 | 
|---|
| [2b596f] | 653 | 
 | 
|---|
 | 654 |     // update bounding box prior to selection
 | 
|---|
| [6c16a0] | 655 |     resetBoundingBox();
 | 
|---|
| [2b596f] | 656 | 
 | 
|---|
 | 657 |     painter->modelViewMatrix().push();
 | 
|---|
 | 658 |     painter->modelViewMatrix().translate(m_position);
 | 
|---|
 | 659 |     if (m_rotationAngle != 0.0f)
 | 
|---|
 | 660 |       painter->modelViewMatrix().rotate(m_rotationAngle, m_rotationVector);
 | 
|---|
| [f47efd4] | 661 |     if ((m_scaleX != 1.0f) || (m_scaleY != 1.0f) || (m_scaleZ != 1.0f))
 | 
|---|
 | 662 |       painter->modelViewMatrix().scale(m_scaleX, m_scaleY, m_scaleZ);
 | 
|---|
| [2b596f] | 663 | 
 | 
|---|
 | 664 |     // Draw a box around the mesh, if selected.
 | 
|---|
 | 665 |     if (m_selected)
 | 
|---|
 | 666 |       drawSelectionBox(painter);
 | 
|---|
 | 667 | 
 | 
|---|
 | 668 |     // Restore the modelview matrix.
 | 
|---|
 | 669 |     painter->modelViewMatrix().pop();
 | 
|---|
| [739ee9] | 670 |   }
 | 
|---|
| [8c001a] | 671 | }
 | 
|---|
 | 672 | 
 | 
|---|
 | 673 | /** Adds an atom of this molecule to the scene.
 | 
|---|
 | 674 |  *
 | 
|---|
 | 675 |  * @param _atom atom to add
 | 
|---|
 | 676 |  */
 | 
|---|
| [2f76d2] | 677 | void GLMoleculeObject_molecule::atomInserted(const atomId_t _id)
 | 
|---|
| [8c001a] | 678 | {
 | 
|---|
| [9c259e] | 679 |   LOG(3, "INFO: GLMoleculeObject_molecule: Received signal atomInserted for atom "+toString(_id)+".");
 | 
|---|
 | 680 | 
 | 
|---|
| [8923ad8] | 681 |   GLMoleculeObject_atom *atomObject = new GLMoleculeObject_atom(GLMoleculeObject::meshSphere, this, _id);
 | 
|---|
 | 682 |   ASSERT( atomObject != NULL,
 | 
|---|
 | 683 |       "GLMoleculeObject_molecule::atomInserted - could not create atom object for "+toString(_id));
 | 
|---|
 | 684 |   AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
 | 
|---|
 | 685 |   ASSERT(iter == AtomsinSceneMap.end(),
 | 
|---|
 | 686 |       "GLMoleculeObject_molecule::atomInserted - same atom with id "+toString(_id)+" added again.");
 | 
|---|
 | 687 |   AtomsinSceneMap.insert( make_pair(_id, atomObject) );
 | 
|---|
 | 688 | 
 | 
|---|
 | 689 |   qRegisterMetaType<atomId_t>("atomId_t");
 | 
|---|
 | 690 |   qRegisterMetaType<bond::ptr>("bond::ptr");
 | 
|---|
 | 691 |   qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
 | 
|---|
 | 692 |   connect (atomObject, SIGNAL(clicked(atomId_t)), this, SIGNAL(atomClicked(atomId_t)));
 | 
|---|
 | 693 |   connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
 | 
|---|
 | 694 |   connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
 | 
|---|
 | 695 |   connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
 | 
|---|
 | 696 |   connect (atomObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
 | 
|---|
| [f714763] | 697 | //  connect (atomObject, SIGNAL(bondsChanged()), this, SLOT(bondInserted(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond)));
 | 
|---|
 | 698 |   connect (atomObject, SIGNAL(BondsInserted(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const atomId_t, const atomId_t, const GLMoleculeObject_bond::SideOfBond)));
 | 
|---|
| [6c16a0] | 699 |   connect (atomObject, SIGNAL(BondsRemoved(const atomId_t, const atomId_t)), this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
 | 
|---|
 | 700 |   connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, const atomId_t, const atomId_t)), this, SLOT(changeAtomId(GLMoleculeObject_atom*, const atomId_t, const atomId_t)));
 | 
|---|
| [8923ad8] | 701 | 
 | 
|---|
 | 702 |   if (m_objectId  == -1)
 | 
|---|
 | 703 |     setObjectId(_id);
 | 
|---|
| [8c001a] | 704 | 
 | 
|---|
| [52cd7b] | 705 |   // add all bonds
 | 
|---|
| [f01769] | 706 |   const atom * const Walker = const_cast<const World &>(World::getInstance()).
 | 
|---|
 | 707 |       getAtom(AtomById(_id));
 | 
|---|
| [704d59] | 708 |   if (Walker != NULL)
 | 
|---|
 | 709 |     addAtomBonds(Walker);
 | 
|---|
 | 710 |   else
 | 
|---|
 | 711 |     ELOG(1, "GLMoleculeObject_atom disappeared while about to add bonds.");
 | 
|---|
| [52cd7b] | 712 | 
 | 
|---|
| [8c001a] | 713 |   emit changeOccured();
 | 
|---|
 | 714 | }
 | 
|---|
 | 715 | 
 | 
|---|
 | 716 | /** Removes an atom of this molecule from the scene.
 | 
|---|
 | 717 |  *
 | 
|---|
 | 718 |  * We just the id as the atom might have already been destroyed.
 | 
|---|
 | 719 |  *
 | 
|---|
 | 720 |  * @param _id id of atom to remove
 | 
|---|
 | 721 |  */
 | 
|---|
| [2f76d2] | 722 | void GLMoleculeObject_molecule::atomRemoved(const atomId_t _id)
 | 
|---|
| [8c001a] | 723 | {
 | 
|---|
| [9c259e] | 724 |   LOG(3, "INFO: GLMoleculeObject_molecule: Received signal atomRemoved for atom "+toString(_id)+".");
 | 
|---|
| [8c001a] | 725 |   // bonds are removed by signal coming from ~bond
 | 
|---|
| [2b596f] | 726 | 
 | 
|---|
| [704d59] | 727 |   if ((unsigned int)m_objectId == _id)
 | 
|---|
| [2b596f] | 728 |     setObjectId(-1);
 | 
|---|
 | 729 | 
 | 
|---|
| [8c001a] | 730 |   // remove atoms
 | 
|---|
 | 731 |   AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
 | 
|---|
 | 732 |   ASSERT(iter != AtomsinSceneMap.end(),
 | 
|---|
| [73b13c] | 733 |       "GLMoleculeObject_molecule::atomRemoved() - atom "+toString(_id)+" not on display.");
 | 
|---|
| [8c001a] | 734 |   GLMoleculeObject_atom *atomObject = iter->second;
 | 
|---|
 | 735 |   AtomsinSceneMap.erase(iter);
 | 
|---|
| [704d59] | 736 |   atomObject->disconnect();
 | 
|---|
| [8c001a] | 737 |   delete atomObject;
 | 
|---|
 | 738 | 
 | 
|---|
 | 739 |   emit changeOccured();
 | 
|---|
 | 740 | }
 | 
|---|
 | 741 | 
 | 
|---|
 | 742 | void GLMoleculeObject_molecule::hoverChangedSignalled(GLMoleculeObject *ob)
 | 
|---|
 | 743 | {
 | 
|---|
 | 744 |   // Find the atom, ob corresponds to.
 | 
|---|
| [704d59] | 745 |   hoverAtomId = -1;
 | 
|---|
| [8c001a] | 746 |   GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
 | 
|---|
 | 747 |   if (atomObject){
 | 
|---|
 | 748 |     for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
 | 
|---|
 | 749 |       if (iter->second == atomObject)
 | 
|---|
| [704d59] | 750 |         hoverAtomId = iter->first;
 | 
|---|
| [8c001a] | 751 |     }
 | 
|---|
 | 752 | 
 | 
|---|
| [2b596f] | 753 |     // Propagate signal.
 | 
|---|
| [704d59] | 754 |     emit hoverChanged(hoverAtomId);
 | 
|---|
| [2b596f] | 755 |   } else {
 | 
|---|
 | 756 |     // Find the atom, ob corresponds to.
 | 
|---|
 | 757 |     GLMoleculeObject_molecule *moleculeObject = dynamic_cast<GLMoleculeObject_molecule *>(ob);
 | 
|---|
 | 758 |     if (moleculeObject == this){
 | 
|---|
 | 759 |       // Propagate signal.
 | 
|---|
| [6c16a0] | 760 |       emit hoverChanged(MolIndex.get(), 0);
 | 
|---|
| [2b596f] | 761 |     }
 | 
|---|
 | 762 |   }
 | 
|---|
| [8c001a] | 763 | }
 | 
|---|
 | 764 | 
 | 
|---|
 | 765 | 
 | 
|---|
 | 766 | /** Helper function to get bond ids in the correct order for BondNodeMap.
 | 
|---|
 | 767 |  *
 | 
|---|
 | 768 |  * \return pair of ids in correct order.
 | 
|---|
 | 769 |  */
 | 
|---|
 | 770 | GLMoleculeObject_molecule::BondIds GLMoleculeObject_molecule::getBondIds(
 | 
|---|
 | 771 |     const bond::ptr _bond,
 | 
|---|
 | 772 |     const enum GLMoleculeObject_bond::SideOfBond _side)
 | 
|---|
 | 773 | {
 | 
|---|
 | 774 |   BondIds ids;
 | 
|---|
 | 775 |   switch (_side) {
 | 
|---|
 | 776 |     case GLMoleculeObject_bond::left:
 | 
|---|
 | 777 |       ids = std::make_pair(_bond->leftatom->getId(), _bond->rightatom->getId());
 | 
|---|
 | 778 |       break;
 | 
|---|
 | 779 |     case GLMoleculeObject_bond::right:
 | 
|---|
 | 780 |       ids = std::make_pair(_bond->rightatom->getId(), _bond->leftatom->getId());
 | 
|---|
 | 781 |       break;
 | 
|---|
 | 782 |   }
 | 
|---|
 | 783 |   return ids;
 | 
|---|
 | 784 | }
 | 
|---|
 | 785 | 
 | 
|---|
 | 786 | /** Adds a bond to the scene.
 | 
|---|
 | 787 |  *
 | 
|---|
 | 788 |  * @param _bond bond to add
 | 
|---|
 | 789 |  * @param side which side of the bond (left or right)
 | 
|---|
 | 790 |  */
 | 
|---|
| [6c16a0] | 791 | void GLMoleculeObject_molecule::bondInserted(
 | 
|---|
 | 792 |     const atomId_t _left, const atomId_t _right,
 | 
|---|
 | 793 |     const enum GLMoleculeObject_bond::SideOfBond _side)
 | 
|---|
| [8c001a] | 794 | {
 | 
|---|
| [6c16a0] | 795 |   LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(_left)
 | 
|---|
 | 796 |       +toString(_right)+".");
 | 
|---|
| [8c001a] | 797 |   //LOG(4, "INFO: Currently present bonds " << BondsinSceneMap << ".");
 | 
|---|
 | 798 | 
 | 
|---|
| [6c16a0] | 799 |   const BondIds ids( std::make_pair(_left, _right) );
 | 
|---|
| [8c001a] | 800 |   BondNodeMap::iterator iter = BondsinSceneMap.find(ids);
 | 
|---|
 | 801 |   if (iter == BondsinSceneMap.end()) {
 | 
|---|
 | 802 |     GLMoleculeObject_bond * bondObject =
 | 
|---|
| [009e2e2] | 803 |         new GLMoleculeObject_bond(GLMoleculeObject::meshCylinder, this, ids, _side);
 | 
|---|
| [8c001a] | 804 |     connect (
 | 
|---|
 | 805 |         bondObject, SIGNAL(BondRemoved(const atomId_t, const atomId_t)),
 | 
|---|
 | 806 |         this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
 | 
|---|
 | 807 |     connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
 | 
|---|
 | 808 |     BondsinSceneMap.insert( make_pair(ids, bondObject) );
 | 
|---|
 | 809 |   //    BondIdsinSceneMap.insert( Leftids );
 | 
|---|
 | 810 |   } else {
 | 
|---|
 | 811 |     iter->second->resetPosition();
 | 
|---|
 | 812 |     iter->second->resetWidth();
 | 
|---|
 | 813 |   }
 | 
|---|
 | 814 |   emit changeOccured();
 | 
|---|
 | 815 | }
 | 
|---|
 | 816 | 
 | 
|---|
 | 817 | /** Removes a bond from the scene.
 | 
|---|
 | 818 |  *
 | 
|---|
 | 819 |  * @param _bond bond to remove
 | 
|---|
 | 820 |  */
 | 
|---|
 | 821 | void GLMoleculeObject_molecule::bondRemoved(const atomId_t leftnr, const atomId_t rightnr)
 | 
|---|
 | 822 | {
 | 
|---|
 | 823 |   LOG(3, "INFO: GLWorldScene::bondRemoved() - Removing bond between "+toString(leftnr)+" and "+toString(rightnr)+".");
 | 
|---|
 | 824 |   {
 | 
|---|
 | 825 |     // left bond
 | 
|---|
 | 826 |     const BondIds Leftids( make_pair(leftnr, rightnr) );
 | 
|---|
 | 827 |     BondNodeMap::iterator leftiter = BondsinSceneMap.find( Leftids );
 | 
|---|
 | 828 |     ASSERT(leftiter != BondsinSceneMap.end(),
 | 
|---|
 | 829 |         "GLWorldScene::bondRemoved() - bond "+toString(leftnr)+"-"
 | 
|---|
 | 830 |         +toString(rightnr)+" not on display.");
 | 
|---|
 | 831 |     GLMoleculeObject_bond *bondObject = leftiter->second;
 | 
|---|
 | 832 |     bondObject->disconnect();
 | 
|---|
 | 833 |     BondsinSceneMap.erase(leftiter);
 | 
|---|
 | 834 |     delete bondObject; // is done by signal from bond itself
 | 
|---|
 | 835 |     //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
 | 
|---|
 | 836 |   }
 | 
|---|
 | 837 | 
 | 
|---|
 | 838 |   emit changeOccured();
 | 
|---|
 | 839 | }
 | 
|---|
 | 840 | 
 | 
|---|
| [34e7fdb] | 841 | void GLMoleculeObject_molecule::setVisible(bool value)
 | 
|---|
 | 842 | {
 | 
|---|
 | 843 |   // first update the mesh if we are going to be visible now
 | 
|---|
 | 844 |   if (value)
 | 
|---|
| [7b5984] | 845 |     updateTesselationHull();
 | 
|---|
| [34e7fdb] | 846 |   // then emit onward
 | 
|---|
 | 847 |   GLMoleculeObject::setVisible(value);
 | 
|---|
 | 848 | }
 | 
|---|
 | 849 | 
 | 
|---|
| [8c001a] | 850 | std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
 | 
|---|
 | 851 | {
 | 
|---|
 | 852 |   ost << t.first << "," << t.second;
 | 
|---|
 | 853 |   return ost;
 | 
|---|
 | 854 | }
 | 
|---|
| [34e7fdb] | 855 | 
 | 
|---|
| [9a7ef9] | 856 | void GLMoleculeObject_molecule::wasClicked()
 | 
|---|
 | 857 | {
 | 
|---|
| [6c16a0] | 858 |   LOG(4, "INFO: GLMoleculeObject_molecule: atom " << MolIndex.get() << " has been clicked");
 | 
|---|
 | 859 |   emit moleculeClicked(MolIndex.get());
 | 
|---|
| [9a7ef9] | 860 | }
 | 
|---|
| [8d3ee6] | 861 | 
 | 
|---|
| [6c16a0] | 862 | void GLMoleculeObject_molecule::changeAtomId(
 | 
|---|
 | 863 |     GLMoleculeObject_atom *ob,
 | 
|---|
 | 864 |     const atomId_t oldId,
 | 
|---|
 | 865 |     const atomId_t newId)
 | 
|---|
| [8d3ee6] | 866 | {
 | 
|---|
 | 867 |   LOG(3, "INFO: GLMoleculeObject_molecule - change atom id " << oldId << " to " << newId << ".");
 | 
|---|
 | 868 | 
 | 
|---|
 | 869 |   // Remove from map.
 | 
|---|
 | 870 |   AtomNodeMap::iterator iter = AtomsinSceneMap.find(oldId);
 | 
|---|
 | 871 |   ASSERT(iter != AtomsinSceneMap.end(),
 | 
|---|
 | 872 |       "GLMoleculeObject_molecule::changeAtomId() - atom with old id "+toString(oldId)+" not on display.");
 | 
|---|
 | 873 |   ASSERT(iter->second == ob,
 | 
|---|
 | 874 |       "GLMoleculeObject_molecule::changeAtomId() - atom with id "
 | 
|---|
 | 875 |       +toString(oldId)+" does not match with object in AtomsinSceneMap.");
 | 
|---|
 | 876 |   AtomsinSceneMap.erase(iter);
 | 
|---|
 | 877 | 
 | 
|---|
 | 878 |   // Reinsert with new id.
 | 
|---|
 | 879 |   {
 | 
|---|
 | 880 |     AtomNodeMap::iterator iter = AtomsinSceneMap.find(newId);
 | 
|---|
 | 881 |     ASSERT(iter == AtomsinSceneMap.end(),
 | 
|---|
 | 882 |           "GLMoleculeObject_molecule::changeAtomId() - atom with new id "+toString(newId)+" already known.");
 | 
|---|
 | 883 |   }
 | 
|---|
 | 884 |   AtomsinSceneMap.insert( make_pair(newId, ob) );
 | 
|---|
 | 885 | }
 | 
|---|
| [6c16a0] | 886 | 
 | 
|---|
 | 887 | const molecule * const GLMoleculeObject_molecule::getMolecule(const moleculeId_t _id)
 | 
|---|
 | 888 | {
 | 
|---|
 | 889 |   const molecule * const mol = const_cast<const World &>(World::getInstance()).
 | 
|---|
 | 890 |       getMolecule(MoleculeById(_id));
 | 
|---|
 | 891 |   return mol;
 | 
|---|
 | 892 | }
 | 
|---|