source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp@ 52cd7b

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 52cd7b was 52cd7b, checked in by Frederik Heber <heber@…>, 10 years ago

FIX: Bonds from new molecules are instantiated, too.

  • when filling in molecules, initially empty molecules are created and atoms added lateron. Added atoms would not add their already present atoms but only new ones via an Observer update. Now when an atom is inserted, all bonds if any are added.
  • Property mode set to 100644
File size: 22.7 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
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/>.
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>
43#include <Qt3D/qglbuilder.h>
44
45#include "CodePatterns/MemDebug.hpp"
46
47#include "CodePatterns/Assert.hpp"
48#include "CodePatterns/Log.hpp"
49#include "CodePatterns/Observer/Notification.hpp"
50#include "CodePatterns/Observer/ObserverLog.hpp"
51
52#include "Atom/atom.hpp"
53#include "molecule.hpp"
54#include "Descriptors/AtomIdDescriptor.hpp"
55#include "Element/element.hpp"
56#include "LinearAlgebra/Vector.hpp"
57#include "LinkedCell/PointCloudAdaptor.hpp"
58#include "LinkedCell/linkedcell.hpp"
59#include "Tesselation/tesselation.hpp"
60#include "Tesselation/BoundaryLineSet.hpp"
61#include "Tesselation/BoundaryTriangleSet.hpp"
62#include "Tesselation/CandidateForTesselation.hpp"
63#include "Atom/TesselPoint.hpp"
64#include "World.hpp"
65
66#include "GLMoleculeObject_atom.hpp"
67
68static QGLSceneNode *createMoleculeMesh(const molecule *molref, QObject *parent)
69{
70// Shape shape = molref->getBoundingSphere();
71 double minradius = 2.; // TODO: set to maximum bond length value
72 LOG(3, "DEBUG: Molecule fits into sphere of radius " << minradius);
73 if (minradius < 1.)
74 minradius = 1.;
75
76 QGeometryData geo;
77 // we need at least three points for tesselation
78 if (molref->getAtomCount() >= 3) {
79 // Tesselate the points.
80 Tesselation T;
81 PointCloudAdaptor<molecule> cloud(const_cast<molecule *>(molref), molref->getName());
82 T(cloud, minradius);
83
84 // Fill the points into a Qt geometry.
85 LinkedCell_deprecated LinkedList(cloud, minradius);
86 std::map<int, int> indices;
87 std::map<int, Vector> normals;
88 int index = 0;
89 for (PointMap::const_iterator piter = T.PointsOnBoundary.begin();
90 piter != T.PointsOnBoundary.end(); ++piter) {
91 const Vector &point = piter->second->getPosition();
92 // add data to the primitive
93 geo.appendVertex(QVector3D(point[0], point[1], point[2]));
94 Vector normalvector;
95 for (LineMap::const_iterator lineiter = piter->second->lines.begin();
96 lineiter != piter->second->lines.end(); ++lineiter)
97 for (TriangleMap::const_iterator triangleiter = lineiter->second->triangles.begin();
98 triangleiter != lineiter->second->triangles.end(); ++triangleiter)
99 normalvector +=
100 triangleiter->second->NormalVector;
101 normalvector.Normalize();
102 geo.appendNormal(QVector3D(normalvector[0], normalvector[1], normalvector[2]));
103 geo.appendColor(QColor(1, 1, 1, 1));
104 geo.appendTexCoord(QVector2D(0, 0));
105 indices.insert( std::make_pair( piter->second->getNr(), index++));
106 }
107
108 // Fill the tesselated triangles into the geometry.
109 for (TriangleMap::const_iterator runner = T.TrianglesOnBoundary.begin();
110 runner != T.TrianglesOnBoundary.end(); runner++) {
111 int v[3];
112 for (size_t i=0; i<3; ++i)
113 v[i] = runner->second->endpoints[i]->getNr();
114
115 // Sort the vertices so the triangle is clockwise (relative to the normal vector).
116 Vector cross = T.PointsOnBoundary[v[1]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition();
117 cross.VectorProduct(T.PointsOnBoundary[v[2]]->getPosition() - T.PointsOnBoundary[v[0]]->getPosition());
118 if (cross.ScalarProduct(runner->second->NormalVector) > 0)
119 geo.appendIndices(indices[v[0]], indices[v[1]], indices[v[2]]);
120 else
121 geo.appendIndices(indices[v[0]], indices[v[2]], indices[v[1]]);
122 }
123 }
124
125 // Build a mesh from the geometry.
126 QGLBuilder builder;
127 builder.addTriangles(geo);
128 QGLSceneNode *mesh = builder.finalizedSceneNode();
129 return mesh;
130}
131
132GLMoleculeObject_molecule::GLMoleculeObject_molecule(QObject *parent, const molecule *molref) :
133 GLMoleculeObject(createMoleculeMesh(molref, parent), parent),
134 Observer(std::string("GLMoleculeObject_molecule")+toString(molref->getId())),
135 isBoundingBoxUptodate(true),
136 isSignedOn(false),
137 _molecule(molref),
138 TesselationHullUptodate(true),
139 hoverAtom(NULL)
140{
141 // sign on as observer (obtain non-const instance before)
142 _molecule->signOn(this, molecule::AtomInserted);
143 _molecule->signOn(this, molecule::AtomRemoved);
144 _molecule->signOn(this, molecule::AtomMoved);
145 isSignedOn = true;
146 /*molref->signOn(this, AtomObservable::IndexChanged);
147 molref->signOn(this, AtomObservable::PositionChanged);
148 molref->signOn(this, AtomObservable::ElementChanged);
149 molref->signOn(this, AtomObservable::BondsAdded);*/
150 setMaterial(getMaterial(1));
151 World::getInstance().signOn(this, World::SelectionChanged);
152 updateBoundingBox();
153
154 // initially, atoms and bonds should be visible
155 m_visible = false;
156
157 init();
158
159 connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
160 connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
161
162 connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
163}
164
165GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const molecule *molref) :
166 GLMoleculeObject(mesh, parent),
167 Observer(std::string("GLMoleculeObject_molecule")+toString(molref->getId())),
168 isBoundingBoxUptodate(true),
169 isSignedOn(false),
170 _molecule(molref),
171 TesselationHullUptodate(true),
172 hoverAtom(NULL)
173{
174 // sign on as observer (obtain non-const instance before)
175 _molecule->signOn(this, molecule::AtomInserted);
176 _molecule->signOn(this, molecule::AtomRemoved);
177 _molecule->signOn(this, molecule::AtomMoved);
178 isSignedOn = true;
179 /*molref->signOn(this, AtomObservable::IndexChanged);
180 molref->signOn(this, AtomObservable::PositionChanged);
181 molref->signOn(this, AtomObservable::ElementChanged);
182 molref->signOn(this, AtomObservable::BondsAdded);*/
183 setMaterial(getMaterial(1));
184 World::getInstance().signOn(this, World::SelectionChanged);
185 updateBoundingBox();
186
187 // initially, atoms and bonds should be visible
188 m_visible = false;
189
190 init();
191
192 connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
193 connect (this, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
194
195 connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
196}
197
198GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
199{
200 if (isSignedOn) {
201 _molecule->signOff(this, molecule::AtomInserted);
202 _molecule->signOff(this, molecule::AtomRemoved);
203 _molecule->signOff(this, molecule::AtomMoved);
204 }
205 /*_atom->signOff(this, AtomObservable::IndexChanged);
206 _atom->signOff(this, AtomObservable::PositionChanged);
207 _atom->signOff(this, AtomObservable::ElementChanged);
208 _atom->signOff(this, AtomObservable::BondsAdded);*/
209 World::getInstance().signOff(this, World::SelectionChanged);
210}
211
212/** Initialise the WorldScene with molecules and atoms from World.
213 *
214 */
215void GLMoleculeObject_molecule::init()
216{
217 if (_molecule->begin() != _molecule->end()) {
218 int atomicid = -1;
219 for (molecule::const_iterator atomiter = _molecule->begin();
220 atomiter != _molecule->end();
221 atomiter++) {
222 // create atom objects in scene
223 atomicid = (*atomiter)->getId();
224 atomInserted(atomicid);
225
226 // create bond objects in scene
227 const BondList &bondlist = (*atomiter)->getListOfBonds();
228 for (BondList::const_iterator bonditer = bondlist.begin();
229 bonditer != bondlist.end();
230 ++bonditer) {
231 const bond::ptr _bond = *bonditer;
232 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == *atomiter) ?
233 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
234 bondInserted(_bond, side);
235 }
236 }
237 // set id to one of the atom's as either mol or atoms is present at the same time
238 setObjectId(atomicid);
239 }
240}
241
242void GLMoleculeObject_molecule::addAtomBonds(
243 const bond::ptr &_bond,
244 const GLMoleculeObject_bond::SideOfBond _side
245 )
246{
247 bool bond_present = false;
248 const BondIds ids = getBondIds(_bond, _side);
249 // check whether bond is not present already
250 bond_present = BondsinSceneMap.count(ids);
251 if (!bond_present)
252 bondInserted(_bond, _side);
253 else {
254 BondsinSceneMap[ids]->resetPosition();
255 BondsinSceneMap[ids]->resetWidth();
256 }
257}
258
259void GLMoleculeObject_molecule::addAtomBonds(
260 const atom *_atom)
261{
262 const bool atom_present = AtomsinSceneMap.count(_atom->getId());
263 const BondList &bondlist = _atom->getListOfBonds();
264 for (BondList::const_iterator bonditer = bondlist.begin();
265 (bonditer != bondlist.end()) && atom_present;
266 ++bonditer) {
267 const bond::ptr _bond = *bonditer;
268 // check if OtherAtom's sphere is already present
269 const atom *OtherAtom = _bond->GetOtherAtom(_atom);
270 const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
271 if (otheratom_present && atom_present) {
272 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
273 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
274 const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
275 GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
276 addAtomBonds(_bond, side);
277 addAtomBonds(_bond, otherside);
278 }
279 }
280}
281
282void GLMoleculeObject_molecule::reinit()
283{
284 if (_molecule->getAtomCount() > 0) {
285 for (molecule::const_iterator atomiter = _molecule->begin();
286 atomiter != _molecule->end();
287 atomiter++) {
288 // check whether atom already exists
289 const atomId_t atomid = (*atomiter)->getId();
290 const bool atom_present = AtomsinSceneMap.count(atomid);
291 if (!atom_present)
292 atomInserted((*atomiter)->getId());
293 else
294 AtomsinSceneMap[atomid]->resetPosition();
295
296
297 // create bond objects in scene
298 addAtomBonds(*atomiter);
299 }
300 }
301}
302
303void GLMoleculeObject_molecule::updateBoundingBox()
304{
305 isBoundingBoxUptodate = true;
306 Shape shape = _molecule->getBoundingSphere();
307 Vector v = shape.getCenter();
308 setPosition(QVector3D(v[0], v[1], v[2]));
309 setScale(shape.getRadius() + 0.3); // getBoundingShape() only sees atoms as points, so make the box a bit bigger
310}
311
312void GLMoleculeObject_molecule::update(Observable *publisher)
313{
314#ifdef LOG_OBSERVER
315 const molecule *_mol = static_cast<molecule *>(publisher);
316 observerLog().addMessage() << "++ Update of Observer " << observerLog().getName(static_cast<Observer *>(this)) << " from molecule "+toString(_mol->getId())+".";
317#endif
318}
319
320void GLMoleculeObject_molecule::subjectKilled(Observable *publisher)
321{
322 isSignedOn = false;
323}
324
325void GLMoleculeObject_molecule::recieveNotification(Observable *publisher, Notification_ptr notification)
326{
327 if (publisher == dynamic_cast<const Observable*>(_molecule)){
328 // notofication from atom
329#ifdef LOG_OBSERVER
330 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
331 << " received notification from molecule " << _molecule->getId() << " for channel "
332 << notification->getChannelNo() << ".";
333#endif
334 switch (notification->getChannelNo()) {
335 case molecule::AtomInserted:
336 {
337 const atomId_t _id = _molecule->lastChanged()->getId();
338 #ifdef LOG_OBSERVER
339 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
340 #endif
341 TesselationHullUptodate = false;
342 isBoundingBoxUptodate = false;
343 atomInserted(_id);
344 break;
345 }
346 case World::AtomRemoved:
347 {
348 const atomId_t _id = _molecule->lastChanged()->getId();
349 #ifdef LOG_OBSERVER
350 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been removed.";
351 #endif
352 TesselationHullUptodate = false;
353 isBoundingBoxUptodate = false;
354 atomRemoved(_id);
355 break;
356 }
357 case molecule::AtomMoved:
358 {
359 #ifdef LOG_OBSERVER
360 const atomId_t _id = _molecule->lastChanged()->getId();
361 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
362 #endif
363 TesselationHullUptodate = false;
364 isBoundingBoxUptodate = false;
365 break;
366 }
367 default:
368 break;
369 }
370 }else{
371 // notification from world
372#ifdef LOG_OBSERVER
373 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
374 << " received notification from world for channel "
375 << notification->getChannelNo() << ".";
376#endif
377 switch (notification->getChannelNo()) {
378 case World::SelectionChanged:
379 setSelected(World::getInstance().isSelected(_molecule));
380 break;
381 default:
382 break;
383 }
384 }
385}
386
387void GLMoleculeObject_molecule::initialize(QGLView *view, QGLPainter *painter)
388{
389 // Initialize all of the mesh objects that we have as children.
390 if (m_visible) {
391 GLMoleculeObject::initialize(view, painter);
392 } else {
393 foreach (QObject *obj, children()) {
394 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
395 if (meshobj)
396 meshobj->initialize(view, painter);
397 }
398 }
399}
400
401void GLMoleculeObject_molecule::draw(QGLPainter *painter, const QVector4D &cameraPlane)
402{
403 // draw either molecule's mesh or all atoms and bonds
404 if (m_visible) {
405 updateTesselationHull();
406
407 painter->modelViewMatrix().push();
408
409 // Apply the material and effect to the painter.
410 QGLMaterial *material;
411 if (m_hovering)
412 material = m_hoverMaterial;
413 else if (m_selected)
414 material = m_selectionMaterial;
415 else
416 material = m_material;
417
418 ASSERT(material, "GLMoleculeObject::draw: chosen material is NULL");
419
420 painter->setColor(material->diffuseColor());
421 painter->setFaceMaterial(QGL::AllFaces, material);
422 if (m_effect)
423 painter->setUserEffect(m_effect);
424 else
425 painter->setStandardEffect(QGL::LitMaterial);
426
427 // Mark the object for object picking purposes.
428 int prevObjectId = painter->objectPickId();
429 if (m_objectId != -1)
430 painter->setObjectPickId(m_objectId);
431
432 m_mesh[0]->draw(painter);
433
434 // Turn off the user effect, if present.
435 if (m_effect)
436 painter->setStandardEffect(QGL::LitMaterial);
437
438 // Revert to the previous object identifier.
439 painter->setObjectPickId(prevObjectId);
440
441 // Restore the modelview matrix.
442 painter->modelViewMatrix().pop();
443
444 // GLMoleculeObject::draw(painter, cameraPlane);
445 } else {
446 // Draw all of the mesh objects that we have as children.
447 foreach (QObject *obj, children()) {
448 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
449 if (meshobj)
450 meshobj->draw(painter, cameraPlane);
451 }
452
453 // update bounding box prior to selection
454 if (!isBoundingBoxUptodate)
455 updateBoundingBox();
456
457 painter->modelViewMatrix().push();
458 painter->modelViewMatrix().translate(m_position);
459 if ((m_scaleX != 1.0f) || (m_scaleY != 1.0f) || (m_scaleZ != 1.0f))
460 painter->modelViewMatrix().scale(m_scaleX, m_scaleY, m_scaleZ);
461 if (m_rotationAngle != 0.0f)
462 painter->modelViewMatrix().rotate(m_rotationAngle, m_rotationVector);
463
464 // Draw a box around the mesh, if selected.
465 if (m_selected)
466 drawSelectionBox(painter);
467
468 // Restore the modelview matrix.
469 painter->modelViewMatrix().pop();
470 }
471}
472
473/** Adds an atom of this molecule to the scene.
474 *
475 * @param _atom atom to add
476 */
477void GLMoleculeObject_molecule::atomInserted(const atomicNumber_t _id)
478{
479 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "+toString(_id)+".");
480 GLMoleculeObject_atom *atomObject = new GLMoleculeObject_atom(GLMoleculeObject::meshSphere, this, _id);
481 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
482 ASSERT(iter == AtomsinSceneMap.end(),
483 "GLWorldScene::atomAdded() - same atom with id "+toString(_id)+" added again.");
484 AtomsinSceneMap.insert( make_pair(_id, atomObject) );
485
486 qRegisterMetaType<atomId_t>("atomId_t");
487 qRegisterMetaType<bond::ptr>("bond::ptr");
488 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
489 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SIGNAL(atomClicked(atomId_t)));
490 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
491 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
492 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
493 connect (atomObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
494 connect (atomObject, SIGNAL(BondsInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)));
495 connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, int, int)), this, SIGNAL(changeAtomId(GLMoleculeObject_atom*, int, int)));
496
497 isBoundingBoxUptodate = false;
498
499 if (m_objectId == -1)
500 setObjectId(_id);
501
502 // add all bonds
503 const atom *Walker = World::getInstance().getAtom(AtomById(_id));
504 addAtomBonds(Walker);
505
506 emit changeOccured();
507}
508
509/** Removes an atom of this molecule from the scene.
510 *
511 * We just the id as the atom might have already been destroyed.
512 *
513 * @param _id id of atom to remove
514 */
515void GLMoleculeObject_molecule::atomRemoved(const atomicNumber_t _id)
516{
517 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_id)+".");
518 // bonds are removed by signal coming from ~bond
519
520 if (m_objectId == _id)
521 setObjectId(-1);
522
523 // remove atoms
524 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
525 ASSERT(iter != AtomsinSceneMap.end(),
526 "GLWorldScene::atomRemoved() - atom "+toString(_id)+" not on display.");
527 GLMoleculeObject_atom *atomObject = iter->second;
528 atomObject->disconnect();
529 AtomsinSceneMap.erase(iter);
530 delete atomObject;
531
532 isBoundingBoxUptodate = false;
533
534 emit changeOccured();
535}
536
537void GLMoleculeObject_molecule::hoverChangedSignalled(GLMoleculeObject *ob)
538{
539 // Find the atom, ob corresponds to.
540 hoverAtom = NULL;
541 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
542 if (atomObject){
543 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
544 if (iter->second == atomObject)
545 hoverAtom = World::getInstance().getAtom(AtomById(iter->first));
546 }
547
548 // Propagate signal.
549 emit hoverChanged(*hoverAtom);
550 } else {
551 // Find the atom, ob corresponds to.
552 GLMoleculeObject_molecule *moleculeObject = dynamic_cast<GLMoleculeObject_molecule *>(ob);
553 if (moleculeObject == this){
554 // Propagate signal.
555 emit hoverChanged(*_molecule, 0);
556 }
557 }
558}
559
560
561/** Helper function to get bond ids in the correct order for BondNodeMap.
562 *
563 * \return pair of ids in correct order.
564 */
565GLMoleculeObject_molecule::BondIds GLMoleculeObject_molecule::getBondIds(
566 const bond::ptr _bond,
567 const enum GLMoleculeObject_bond::SideOfBond _side)
568{
569 BondIds ids;
570 switch (_side) {
571 case GLMoleculeObject_bond::left:
572 ids = std::make_pair(_bond->leftatom->getId(), _bond->rightatom->getId());
573 break;
574 case GLMoleculeObject_bond::right:
575 ids = std::make_pair(_bond->rightatom->getId(), _bond->leftatom->getId());
576 break;
577 }
578 return ids;
579}
580
581/** Adds a bond to the scene.
582 *
583 * @param _bond bond to add
584 * @param side which side of the bond (left or right)
585 */
586void GLMoleculeObject_molecule::bondInserted(const bond::ptr _bond, const enum GLMoleculeObject_bond::SideOfBond _side)
587{
588 LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(*_bond)+".");
589 //LOG(4, "INFO: Currently present bonds " << BondsinSceneMap << ".");
590
591 const BondIds ids = getBondIds(_bond, _side);
592 BondNodeMap::iterator iter = BondsinSceneMap.find(ids);
593 if (iter == BondsinSceneMap.end()) {
594 GLMoleculeObject_bond * bondObject =
595 new GLMoleculeObject_bond(GLMoleculeObject::meshCylinder, this, _bond, _side);
596 connect (
597 bondObject, SIGNAL(BondRemoved(const atomId_t, const atomId_t)),
598 this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
599 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
600 BondsinSceneMap.insert( make_pair(ids, bondObject) );
601 // BondIdsinSceneMap.insert( Leftids );
602 } else {
603 iter->second->resetPosition();
604 iter->second->resetWidth();
605 }
606 emit changeOccured();
607}
608
609/** Removes a bond from the scene.
610 *
611 * @param _bond bond to remove
612 */
613void GLMoleculeObject_molecule::bondRemoved(const atomId_t leftnr, const atomId_t rightnr)
614{
615 LOG(3, "INFO: GLWorldScene::bondRemoved() - Removing bond between "+toString(leftnr)+" and "+toString(rightnr)+".");
616 {
617 // left bond
618 const BondIds Leftids( make_pair(leftnr, rightnr) );
619 BondNodeMap::iterator leftiter = BondsinSceneMap.find( Leftids );
620 ASSERT(leftiter != BondsinSceneMap.end(),
621 "GLWorldScene::bondRemoved() - bond "+toString(leftnr)+"-"
622 +toString(rightnr)+" not on display.");
623 GLMoleculeObject_bond *bondObject = leftiter->second;
624 bondObject->disconnect();
625 BondsinSceneMap.erase(leftiter);
626 delete bondObject; // is done by signal from bond itself
627 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
628 }
629
630 emit changeOccured();
631}
632
633void GLMoleculeObject_molecule::setVisible(bool value)
634{
635 // first update the mesh if we are going to be visible now
636 if (value)
637 updateTesselationHull();
638 // then emit onward
639 GLMoleculeObject::setVisible(value);
640}
641
642void GLMoleculeObject_molecule::updateTesselationHull()
643{
644 if (!TesselationHullUptodate) {
645 updateMesh(createMoleculeMesh(_molecule, parent()));
646 TesselationHullUptodate = true;
647 }
648}
649
650std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
651{
652 ost << t.first << "," << t.second;
653 return ost;
654}
655
656void GLMoleculeObject_molecule::wasClicked()
657{
658 LOG(4, "INFO: GLMoleculeObject_molecule: atom " << _molecule->getId() << " has been clicked");
659 emit moleculeClicked(_molecule->getId());
660}
Note: See TracBrowser for help on using the repository browser.