source: src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp@ 30b134

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 30b134 was 30b134, checked in by Frederik Heber <heber@…>, 9 years ago

FIX: GLWorldScene::removeBond() needs to check whether molecule changed already.

  • there are two possibilities for bonds to be removed: Either the molecule is removed (with its atoms) and this one we got so far. Or the bond is simply removed (because auf adjacency recreation) and this we did not check so far.
  • If the simply the bond is removed, then we receive removeBond() but no moleculeChanged() signals. Hence, the QtObservedBond is never removed. We need to check in removeBonds() whether the associated molecules are not NULL and then reset the parent entries ourselves.
  • Property mode set to 100644
File size: 34.1 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 * GLWorldScene.cpp
26 *
27 * This is based on the Qt3D example "teaservice", specifically parts of teaservice.cpp.
28 *
29 * Created on: Aug 17, 2011
30 * Author: heber
31 */
32
33// include config.h
34#ifdef HAVE_CONFIG_H
35#include <config.h>
36#endif
37
38#include "GLWorldScene.hpp"
39#include <Qt3D/qglview.h>
40#include <Qt3D/qglbuilder.h>
41#include <Qt3D/qglscenenode.h>
42#include <Qt3D/qglsphere.h>
43#include <Qt3D/qglcylinder.h>
44
45#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject.hpp"
46#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.hpp"
47#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_bond.hpp"
48#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.hpp"
49#include "UIElements/Views/Qt4/Qt3D/GLMoleculeObject_shape.hpp"
50
51#include "UIElements/Qt4/InstanceBoard/QtObservedInstanceBoard.hpp"
52
53#include "CodePatterns/MemDebug.hpp"
54
55#include "CodePatterns/Log.hpp"
56
57#include <boost/assign.hpp>
58
59#include "Actions/SelectionAction/Atoms/AtomByIdAction.hpp"
60#include "Actions/SelectionAction/Atoms/NotAtomByIdAction.hpp"
61#include "Actions/SelectionAction/Molecules/MoleculeByIdAction.hpp"
62#include "Actions/SelectionAction/Molecules/NotMoleculeByIdAction.hpp"
63#include "Atom/atom.hpp"
64#include "Bond/bond.hpp"
65#include "Descriptors/AtomIdDescriptor.hpp"
66#include "Descriptors/MoleculeIdDescriptor.hpp"
67#include "Helpers/helpers.hpp"
68#include "Shapes/ShapeRegistry.hpp"
69#include "molecule.hpp"
70#include "World.hpp"
71
72#include <iostream>
73
74using namespace MoleCuilder;
75
76// static functions
77
78static void eraseBondNodeParents(
79 std::vector<GLWorldScene::BondNodeParentMap_t> &_BondNodeParentMaps,
80 const ObservedValue_Index_t &_bondid)
81{
82 const size_t left_erased = _BondNodeParentMaps[0].left.erase(_bondid);
83 const size_t right_erased = _BondNodeParentMaps[1].left.erase(_bondid);
84 ASSERT( (left_erased == 1) && (right_erased == 1),
85 "eraseBondNodeParents() - could not erase both parents of "+toString(_bondid)+"?");
86}
87
88/** Checks whether both parents of the bond are set to GLWorldScene and the
89 * bondRemoved() signals was received for this bond.
90 *
91 * \param _BondNodeParent_Maps - map containing parents
92 * \param _ToBeRemovedNodes - set with all bonds that are to be removed
93 * \param _bondid id of bond
94 * \return true - both parents are assigned to GLWorldScene, false - else
95 */
96static bool checkBondRemoval(
97 const std::vector<GLWorldScene::BondNodeParentMap_t> &_BondNodeParentMaps,
98 const GLWorldScene::ToBeRemovedNodes_t &_ToBeRemovedNodes,
99 const ObservedValue_Index_t &_bondid)
100{
101 GLWorldScene::BondNodeParentMap_t::left_const_iterator leftiter =
102 _BondNodeParentMaps[0].left.find(_bondid);
103 GLWorldScene::BondNodeParentMap_t::left_const_iterator rightiter =
104 _BondNodeParentMaps[1].left.find(_bondid);
105 ASSERT( leftiter != _BondNodeParentMaps[0].left.end(),
106 "checkBondRemoval() - left parent to index "+toString(_bondid)+" missing?");
107 ASSERT( rightiter != _BondNodeParentMaps[1].left.end(),
108 "checkBondRemoval() - right parent to index "+toString(_bondid)+" missing?");
109 return ((leftiter->second == (ObservedValue_Index_t)NULL)
110 && (rightiter->second == (ObservedValue_Index_t)NULL)
111 && (_ToBeRemovedNodes.count(_bondid)));
112}
113
114void removeBondFromScene(
115 GLWorldScene::BondNodeMap &_BondsinSceneMap,
116 const ObservedValue_Index_t &_bondid)
117{
118 std::pair<GLWorldScene::BondNodeMap::iterator, GLWorldScene::BondNodeMap::iterator> iters =
119 _BondsinSceneMap.equal_range(_bondid);
120 ASSERT( iters.first != iters.second,
121 "removeBondFromScene() - could not find bond to id "+toString(_bondid));
122 for (GLWorldScene::BondNodeMap::iterator iter = iters.first; iter != iters.second; ++iter) {
123 GLMoleculeObject_bond *bondObject = iter->second;
124 delete bondObject; // is done by signal from bond itself
125 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
126 }
127 _BondsinSceneMap.erase(_bondid);
128}
129
130static bool checkAtomRemoval(
131 const GLWorldScene::AtomNodeParentMap_t &_AtomNodeParentMap,
132 const GLWorldScene::ToBeRemovedNodes_t &_ToBeRemovedNodes,
133 const ObservedValue_Index_t &_atomid)
134{
135 GLWorldScene::AtomNodeParentMap_t::left_const_iterator iter = _AtomNodeParentMap.left.find(_atomid);
136 ASSERT( iter != _AtomNodeParentMap.left.end(),
137 "checkAtomRemoval() - missing parent entry for "+toString(_atomid));
138 return ((iter->second == (ObservedValue_Index_t)NULL) && (_ToBeRemovedNodes.count(_atomid)));
139}
140
141// class definitions
142
143GLWorldScene::GLWorldScene(
144 QtObservedInstanceBoard * _board,
145 QObject *parent) :
146 QObject(parent),
147 BondNodeParentMaps(std::vector<BondNodeParentMap_t>(2)),
148 selectionMode(SelectAtom),
149 board(_board)
150{
151 qRegisterMetaType<atomId_t>("atomId_t");
152 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
153
154 int sphereDetails[] = {5, 3, 2, 0};
155 int cylinderDetails[] = {16, 8, 6, 3};
156 for (int i=0;i<GLMoleculeObject::DETAILTYPES_MAX;i++){
157 QGLBuilder emptyBuilder;
158 GLMoleculeObject::meshEmpty[i] = emptyBuilder.finalizedSceneNode();
159 QGLBuilder sphereBuilder;
160 sphereBuilder << QGLSphere(2.0, sphereDetails[i]);
161 GLMoleculeObject::meshSphere[i] = sphereBuilder.finalizedSceneNode();
162 GLMoleculeObject::meshSphere[i]->setOption(QGLSceneNode::CullBoundingBox, true);
163 QGLBuilder cylinderBuilder;
164 cylinderBuilder << QGLCylinder(.25,.25,1.0,cylinderDetails[i]);
165 GLMoleculeObject::meshCylinder[i] = cylinderBuilder.finalizedSceneNode();
166 GLMoleculeObject::meshCylinder[i]->setOption(QGLSceneNode::CullBoundingBox, true);
167 }
168 connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)),
169 this, SLOT(insertMolecule(QtObservedMolecule::ptr)));
170 connect(board, SIGNAL(moleculeRemoved(ObservedValue_Index_t)),
171 this, SLOT(removeMolecule(ObservedValue_Index_t)));
172
173 connect(board, SIGNAL(atomInserted(QtObservedAtom::ptr)),
174 this, SLOT(connectAtom(QtObservedAtom::ptr)), Qt::DirectConnection);
175 connect(this, SIGNAL(atomConnected(QtObservedAtom::ptr)),
176 this, SLOT(insertAtom(QtObservedAtom::ptr)));
177 connect(board, SIGNAL(atomRemoved(ObservedValue_Index_t)),
178 this, SLOT(removeAtom(ObservedValue_Index_t)));
179
180 connect(board, SIGNAL(bondInserted(QtObservedBond::ptr)),
181 this, SLOT(connectBond(QtObservedBond::ptr)), Qt::DirectConnection);
182 connect(this, SIGNAL(bondConnected(QtObservedBond::ptr)),
183 this, SLOT(insertBond(QtObservedBond::ptr)));
184 connect(board, SIGNAL(bondRemoved(ObservedValue_Index_t)),
185 this, SLOT(removeBond(ObservedValue_Index_t)));
186
187// connect(this, SIGNAL(updated()), this, SLOT(update()));
188}
189
190GLWorldScene::~GLWorldScene()
191{
192 // remove all elements
193 GLMoleculeObject::cleanMaterialMap();
194}
195
196void GLWorldScene::clickAtom(atomId_t no)
197{
198 LOG(3, "INFO: GLWorldScene - atom " << no << " has been clicked.");
199 const atom * const Walker = const_cast<const World &>(World::getInstance()).
200 getAtom(AtomById(no));
201 ASSERT( Walker != NULL,
202 "GLWorldScene::clickAtom() - clicked atom has disappeared.");
203 if (selectionMode == SelectAtom){
204 if (!World::getInstance().isSelected(Walker))
205 SelectionAtomById(std::vector<atomId_t>(1,no));
206 else
207 SelectionNotAtomById(std::vector<atomId_t>(1,no));
208 }else if (selectionMode == SelectMolecule){
209 const molecule *mol = Walker->getMolecule();
210 ASSERT(mol, "Atom without molecule has been clicked.");
211 molids_t ids(1, mol->getId());
212 if (!World::getInstance().isSelected(mol))
213 SelectionMoleculeById(ids);
214 else
215 SelectionNotMoleculeById(ids);
216 }
217 emit clicked(no);
218}
219
220/** Prepares adding an atom to the scene
221 *
222 * We need to listen to moleculeChanged() in order to properly re-parent()
223 * this QObject
224 *
225 * @param _atom atom to connect
226 */
227void GLWorldScene::connectAtom(QtObservedAtom::ptr _atom)
228{
229 connect(_atom.get(), SIGNAL(moleculeChanged()), this, SLOT(reparentAtom()));
230
231 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
232
233 // store the object, as we need it on reparenting
234 const ObservedValue_Index_t atomid = _atom->getIndex();
235#ifndef NDEBUG
236 std::pair< ObservedAtoms_t::iterator, bool > inserter =
237#endif
238 ObservedAtoms.insert( std::make_pair(_atom.get(), _atom) );
239 ASSERT( inserter.second,
240 "GLWorldScene::connectAtom() - observed atom "+toString(_atom)+" already stored?");
241#ifndef NDEBUG
242 std::pair< ObservedValueIndexLookup_t::iterator, bool > indexinserter =
243#endif
244 ObservedAtomIndexLookup.insert( std::make_pair(atomid, _atom.get()) );
245 ASSERT( indexinserter.second,
246 "GLWorldScene::connectAtom() - observed atom's index "
247 +toString(atomid)+" already stored?");
248
249 // and create entry in the parent map
250 AtomNodeParentMap.left.insert( std::make_pair(atomid, (ObservedValue_Index_t)NULL) );
251
252 emit atomConnected(_atom);
253}
254
255/** Adds an atom to the scene.
256 *
257 * @param _atom atom to add
258 */
259void GLWorldScene::insertAtom(QtObservedAtom::ptr _atom)
260{
261 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "
262 << _atom->getAtomIndex());
263 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
264
265 const ObservedValue_Index_t atomid = _atom->getIndex();
266 QObject *parent = static_cast<QObject *>(this);
267 GLMoleculeObject_atom *atomObject = NULL;
268 {
269 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(atomid);
270 ASSERT (parentiter != AtomNodeParentMap.left.end(),
271 "GLWorldScene::insertAtom() - parent to atom id "+toString(atomid)+" unknown?");
272 const ObservedValue_Index_t parentindex = parentiter->second;
273 if (parentindex != (ObservedValue_Index_t)NULL) {
274 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentindex);
275 if (moliter != MoleculesinSceneMap.end())
276 parent = moliter->second;
277 }
278
279 atomObject = new GLMoleculeObject_atom(
280 GLMoleculeObject::meshSphere,
281 parent,
282 _atom);
283 ASSERT( atomObject != NULL,
284 "GLWorldScene::atomInserted - could not create atom object for "
285 +toString(_atom->getAtomIndex()));
286 }
287 AtomNodeMap::iterator iter = AtomsinSceneMap.find(atomid);
288 ASSERT(iter == AtomsinSceneMap.end(),
289 "GLWorldScene::insertAtom - same atom with id "
290 +toString(_atom->getAtomIndex())+" added again.");
291 AtomsinSceneMap.insert( make_pair(atomid, atomObject) );
292
293 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SLOT(clickAtom(atomId_t)));
294 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
295 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
296 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
297
298 emit changed();
299 emit changeOccured();
300}
301
302template <class T>
303void removeStoredObservedValue(
304 GLWorldScene::ObservedValueIndexLookup_t &_ObservedValueIndexLookup,
305 T &_ObservedValues,
306 const ObservedValue_Index_t &_id)
307{
308 // get QObject* from lookup
309 const GLWorldScene::ObservedValueIndexLookup_t::iterator iter =
310 _ObservedValueIndexLookup.find(_id);
311 ASSERT( iter != _ObservedValueIndexLookup.end(),
312 "removeStoredObservedValue() - could not find index "+toString(_id)
313 +" to stored observed value.");
314 QObject * sender = iter->second;
315 const size_t erased = _ObservedValues.erase(sender);
316 ASSERT( erased == 1,
317 "removeStoredObservedValue() - could not erase stored observed value "
318 +toString(_id));
319 _ObservedValueIndexLookup.erase(iter);
320}
321
322void removeAtomFromScene(
323 GLWorldScene::AtomNodeMap &_AtomsinSceneMap,
324 const ObservedValue_Index_t &_atomid)
325{
326 GLWorldScene::AtomNodeMap::iterator iter = _AtomsinSceneMap.find(_atomid);
327 ASSERT(iter != _AtomsinSceneMap.end(),
328 "removeAtomFromScene() - atom "+toString(_atomid)+" not on display.");
329 GLMoleculeObject_atom *atomObject = iter->second;
330 _AtomsinSceneMap.erase(iter);
331 delete atomObject;
332}
333
334void GLWorldScene::checkAndRemoveAtom(const ObservedValue_Index_t &_atomid)
335{
336 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
337
338 if (checkAtomRemoval(AtomNodeParentMap, ToBeRemovedNodes, _atomid)) {
339 LOG(4, "DEBUG: Found parent of to be removed atom as GLWorldScene, removing.");
340 removeAtomFromScene(AtomsinSceneMap, _atomid);
341 AtomNodeParentMap.left.erase(_atomid);
342 ToBeRemovedNodes.erase(_atomid);
343 removeStoredObservedValue(ObservedAtomIndexLookup, ObservedAtoms, _atomid);
344 }
345}
346
347/** Removes an atom.
348 *
349 * @param _atomid index of the atom that is removed
350 */
351void GLWorldScene::removeAtom(ObservedValue_Index_t _atomid)
352{
353 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+".");
354 // bonds are removed by signal coming from ~bond
355 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
356
357 ASSERT( ToBeRemovedNodes.count(_atomid) == 0,
358 "GLWorldScene::removeAtom() - removedAtom signal for id "+toString(_atomid)
359 +" came in twice?");
360 ToBeRemovedNodes.insert( _atomid );
361
362 // remove atoms
363 checkAndRemoveAtom( _atomid );
364
365 emit changed();
366 emit changeOccured();
367}
368
369/** Prepares adding a bond to the scene
370 *
371 * We need to listen to moleculeChanged() in order to properly re-parent()
372 * this QObject
373 *
374 * @param _bond bond to connect
375 */
376void GLWorldScene::connectBond(QtObservedBond::ptr _bond)
377{
378 LOG(3, "INFO: GLWorldScene::connectBond() - connecting to bonds " << _bond->getBondIndex());
379
380 connect(_bond.get(), SIGNAL(leftmoleculeChanged()), this, SLOT(reparentBondLeft()), Qt::QueuedConnection);
381 connect(_bond.get(), SIGNAL(rightmoleculeChanged()), this, SLOT(reparentBondRight()), Qt::QueuedConnection);
382
383 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
384
385 // store the object, as we need it on reparenting
386 const ObservedValue_Index_t bondid = _bond->getIndex();
387 {
388#ifndef NDEBUG
389 std::pair< ObservedBonds_t::iterator, bool > inserter =
390#endif
391 ObservedBonds.insert( std::make_pair(_bond.get(), _bond) );
392 ASSERT( inserter.second,
393 "GLWorldScene::connectBond() - observed bond "+toString(_bond)+" already stored?");
394#ifndef NDEBUG
395 std::pair< ObservedValueIndexLookup_t::iterator, bool > indexinserter =
396#endif
397 ObservedBondIndexLookup.insert( std::make_pair(bondid, _bond.get()) );
398 ASSERT( indexinserter.second,
399 "GLWorldScene::connectBond() - observed bond's index "
400 +toString(bondid)+" already stored?");
401 }
402 {
403 if ((_bond->getLeftAtom() != NULL) && (_bond->getLeftAtom()->getMoleculeRef() != NULL))
404 BondNodeParentMaps[0].left.insert(
405 std::make_pair(bondid, _bond->getLeftAtom()->getMoleculeRef()->getIndex()) );
406 else
407 BondNodeParentMaps[0].left.insert(
408 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
409 if ((_bond->getRightAtom() != NULL) && (_bond->getRightAtom()->getMoleculeRef() != NULL))
410 BondNodeParentMaps[1].left.insert(
411 std::make_pair(bondid, _bond->getRightAtom()->getMoleculeRef()->getIndex()) );
412 else
413 BondNodeParentMaps[1].left.insert(
414 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
415 }
416
417 emit bondConnected(_bond);
418}
419
420/** Adds a bond to the scene.
421 *
422 * @param _bond bond to add
423 */
424void GLWorldScene::insertBond(QtObservedBond::ptr _bond)
425{
426 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
427
428 const std::vector< GLMoleculeObject_bond::SideOfBond > bondsides =
429 boost::assign::list_of<GLMoleculeObject_bond::SideOfBond>
430 (GLMoleculeObject_bond::left)
431 (GLMoleculeObject_bond::right);
432 LOG(3, "INFO: GLWorldScene::insertBond() - Adding bonds " << _bond->getBondIndex());
433
434 const ObservedValue_Index_t bondid = _bond->getIndex();
435#ifdef NDEBUG
436 BondNodeMap::iterator iter = BondsinSceneMap.find(bondid);
437 ASSERT( iter == BondsinSceneMap.end(),
438 "GLWorldScene::insertBond() - bond "+toString(bondid)+" is already known.");
439#endif
440 {
441 for (size_t i=0;i<2;++i) {
442 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[i].left.find(bondid);
443 ASSERT (parentiter != BondNodeParentMaps[i].left.end(),
444 "GLWorldScene::insertBond() - parent to bond id "+toString(bondid)+" unknown?");
445 QObject *parent = this;
446 if (parentiter->second != (ObservedValue_Index_t)NULL) {
447 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentiter->second);
448 if (moliter != MoleculesinSceneMap.end())
449 parent = moliter->second;
450 }
451
452 GLMoleculeObject_bond *bondObject = new GLMoleculeObject_bond(
453 GLMoleculeObject::meshCylinder,
454 parent,
455 _bond,
456 bondsides[i]);
457 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
458 BondsinSceneMap.insert( std::make_pair(bondid, bondObject) );
459 }
460 }
461
462 emit changed();
463 emit changeOccured();
464}
465
466void GLWorldScene::checkAndRemoveBond(const ObservedValue_Index_t &_bondid)
467{
468 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
469
470 if (checkBondRemoval(BondNodeParentMaps, ToBeRemovedNodes, _bondid)) {
471 LOG(3, "DEBUG: Found both parents of to be removed bond " << _bondid << " as GLWorldScene, removing.");
472 removeBondFromScene(BondsinSceneMap, _bondid);
473 removeStoredObservedValue(ObservedBondIndexLookup, ObservedBonds, _bondid);
474 eraseBondNodeParents(BondNodeParentMaps, _bondid);
475 ToBeRemovedNodes.erase(_bondid);
476 }
477}
478
479/** Removes a bond.
480 *
481 * @param _bondid id of bond to remove
482 */
483void GLWorldScene::removeBond(ObservedValue_Index_t _bondid)
484{
485 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
486 LOG(3, "INFO: GLWorldScene::removedBond() - got bondRemoved signal from board for id " << _bondid);
487
488 // check current state of associated molecules: We won't receive any
489 // moleculeChanged() here anymore, as this QtObservedBond is already
490 // disconnected from its bond object
491 {
492 const ObservedValueIndexLookup_t::const_iterator objiter = ObservedBondIndexLookup.find(_bondid);
493 ASSERT( objiter != ObservedBondIndexLookup.end(),
494 "GLWorldScene::removeBond() - bond's index "+toString(_bondid)
495 +" to be removed not stored yet?");
496 QObject *obj = objiter->second;
497 const ObservedBonds_t::const_iterator observediter = ObservedBonds.find(obj);
498 ASSERT( observediter != ObservedBonds.end(),
499 "GLWorldScene::removeBond() - bond "+toString(_bondid)
500 +" to be removed not stored yet??");
501 const QtObservedBond::ptr &_bond = observediter->second;
502 if (_bond->getLeftMoleculeIndex() != (moleculeId_t)-1) {
503 BondNodeParentMaps[0].left.erase(_bondid);
504 BondNodeParentMaps[0].left.insert( std::make_pair( _bondid, (ObservedValue_Index_t)NULL) );
505 resetParent(getBondInScene(_bondid, GLMoleculeObject_bond::left), NULL);
506 }
507 if (_bond->getRightMoleculeIndex() != (moleculeId_t)-1) {
508 BondNodeParentMaps[1].left.erase(_bondid);
509 BondNodeParentMaps[1].left.insert( std::make_pair( _bondid, (ObservedValue_Index_t)NULL) );
510 resetParent(getBondInScene(_bondid, GLMoleculeObject_bond::right), NULL);
511 }
512 }
513
514 ASSERT( ToBeRemovedNodes.find(_bondid) == ToBeRemovedNodes.end(),
515 "GLWorldScene::removeBond() - bondRemoved for "+toString(_bondid)+" obtained twice?");
516 ToBeRemovedNodes.insert( _bondid );
517
518 // check whether node has still non-NULL parents, otherwise remove completely
519 checkAndRemoveBond( _bondid );
520
521 emit changed();
522 emit changeOccured();
523}
524
525void GLWorldScene::hoverChangedSignalled(GLMoleculeObject *ob)
526{
527 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
528 // Find the atom, ob corresponds to.
529 hoverAtomId = -1;
530 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
531 if (atomObject){
532 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
533 if (iter->second == atomObject)
534 hoverAtomId = iter->second->objectId();
535 }
536
537 // Propagate signal.
538 emit hoverChanged(hoverAtomId);
539 } else {
540 // Find the atom, ob corresponds to.
541 GLMoleculeObject_molecule *moleculeObject = dynamic_cast<GLMoleculeObject_molecule *>(ob);
542 if (moleculeObject){
543 // Propagate signal.
544 emit hoverChanged(moleculeObject->objectId(), 0);
545 }
546 }
547}
548
549void GLWorldScene::clickMolecule(moleculeId_t no)
550{
551 LOG(3, "INFO: GLMoleculeObject_molecule - mol " << no << " has been clicked.");
552 const molecule * const mol= const_cast<const World &>(World::getInstance()).
553 getMolecule(MoleculeById(no));
554 ASSERT(mol, "Atom without molecule has been clicked.");
555 molids_t ids(1, mol->getId());
556 if (!World::getInstance().isSelected(mol))
557 SelectionMoleculeById(ids);
558 else
559 SelectionNotMoleculeById(ids);
560 emit clicked(no);
561}
562
563/** Inserts a molecule into the scene.
564 *
565 * @param _mol molecule to insert
566 */
567void GLWorldScene::insertMolecule(QtObservedMolecule::ptr _mol)
568{
569 const ObservedValue_Index_t molid = _mol->getIndex();
570 LOG(3, "INFO: GLWorldScene: Received signal moleculeInserted for molecule "
571 << _mol->getMolIndex());
572
573 MoleculeNodeMap::const_iterator iter = MoleculesinSceneMap.find(molid);
574 ASSERT( iter == MoleculesinSceneMap.end(),
575 "GLWorldScene::insertMolecule() - molecule's id "+toString(molid)
576 +" already present.");
577
578 // add new object
579 LOG(1, "DEBUG: Adding GLMoleculeObject_molecule to id " << molid);
580 GLMoleculeObject_molecule *molObject =
581 new GLMoleculeObject_molecule(
582 GLMoleculeObject::meshEmpty,
583 this,
584 _mol);
585 ASSERT( molObject != NULL,
586 "GLWorldScene::insertMolecule - could not create molecule object for "
587 +toString(molid));
588#ifndef NDEBUG
589 foreach (QObject *obj, molObject->children()) {
590 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
591 ASSERT( meshobj == NULL,
592 "GLWorldScene::insertMolecule() - there are already atoms or bonds attached to a to molecule.");
593 }
594#endif
595
596 // check all atoms for not yet assigned parents
597 {
598 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
599 std::pair<AtomNodeParentMap_t::right_const_iterator, AtomNodeParentMap_t::right_const_iterator> iters =
600 AtomNodeParentMap.right.equal_range(molid);
601 for (AtomNodeParentMap_t::right_const_iterator iter = iters.first;
602 iter != iters.second; ++iter) {
603 AtomNodeMap::const_iterator atomiter = AtomsinSceneMap.find(iter->second);
604 if (atomiter != AtomsinSceneMap.end())
605 resetParent(atomiter->second, molObject);
606 }
607 }
608 // check all bonds for not yet assigned parents
609 {
610 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
611 for (size_t i=0;i<2;++i) {
612 std::pair<BondNodeParentMap_t::right_const_iterator, BondNodeParentMap_t::right_const_iterator> iters =
613 BondNodeParentMaps[i].right.equal_range(molid);
614 for (BondNodeParentMap_t::right_const_iterator iter = iters.first;
615 iter != iters.second; ++iter) {
616 BondNodeMap::const_iterator bonditer = BondsinSceneMap.find(iter->second);
617 if (bonditer != BondsinSceneMap.end())
618 resetParent(bonditer->second, molObject);
619 }
620 }
621 }
622
623#ifndef NDEBUG
624 std::pair<MoleculeNodeMap::iterator, bool> inserter =
625#endif
626 MoleculesinSceneMap.insert( make_pair(molid, molObject) );
627 ASSERT(inserter.second,
628 "GLWorldScene::insertMolecule() - molecule "+toString(_mol->getMolIndex())
629 +" already present in scene.");
630
631 connect (molObject, SIGNAL(changed()), this, SIGNAL(changed()));
632 connect (molObject, SIGNAL(changeOccured()), this, SIGNAL(changeOccured()));
633
634 emit changed();
635 emit changeOccured();
636}
637
638/** Removes a molecule from the scene.
639 *
640 * @param _molid index of the molecule to remove
641 */
642void GLWorldScene::removeMolecule(ObservedValue_Index_t _molid)
643{
644 LOG(3, "INFO: GLWorldScene: Received signal moleculeRemoved for molecule "+toString(_molid)+".");
645
646 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
647 ASSERT ( iter != MoleculesinSceneMap.end(),
648 "GLWorldScene::removeMolecule() - to be removed molecule "+toString(_molid)
649 +" is already gone.");
650 GLMoleculeObject_molecule *molObject = iter->second;
651 // check for any atoms and bonds still attached to it
652#ifndef NDEBUG
653 foreach (QObject *obj, molObject->children()) {
654 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
655 ASSERT( meshobj == NULL,
656 "GLWorldScene::removeMolecule() - there are still atoms or bonds attached to a to molecule.");
657 }
658#endif
659 // finally, remove molecule
660 delete molObject;
661 MoleculesinSceneMap.erase(iter);
662
663 emit changed();
664 emit changeOccured();
665}
666
667void GLWorldScene::moleculesVisibilityChanged(ObservedValue_Index_t _id, bool _visible)
668{
669 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
670 ASSERT( iter != MoleculesinSceneMap.end(),
671 "GLWorldScene::moleculeInserted() - molecule's id "
672 +toString(board->getMoleculeIdToIndex(_id))+" is unknown.");
673
674 GLMoleculeObject_molecule *molObject = iter->second;
675 molObject->setVisible(_visible);
676
677 emit changed();
678 emit changeOccured();
679}
680
681/** This converts safely index into a GLMoleculeObject_molecule.
682 *
683 * \param _MoleculesinSceneMap all present molecules
684 * \param _molid index to look for
685 * \return MolObject or NULL when not found
686 */
687GLMoleculeObject_molecule *GLWorldScene::getMoleculeObject(
688 const ObservedValue_Index_t _molid) const
689{
690 const MoleculeNodeMap::const_iterator moliter = MoleculesinSceneMap.find(_molid);
691 if (moliter != MoleculesinSceneMap.end())
692 return moliter->second;
693 else
694 return NULL;
695}
696
697/** Changes the parent of an object in the scene.
698 *
699 * \param _id index of the object whose parent to change
700 * \param _ob new parent
701 */
702void GLWorldScene::reparentAtom()
703{
704 boost::recursive_mutex::scoped_lock lock(Atom_mutex);
705 QObject * origin = sender();
706 if (origin == NULL) {
707 ELOG(1, "Got reparentAtom() with sender being NULL.");
708 return;
709 }
710 ObservedAtoms_t::const_iterator iter = ObservedAtoms.find(origin);
711 ASSERT( iter != ObservedAtoms.end(),
712 "GLWorldScene::reparentAtom() - atom's "+toString(origin)+" is no longer stored?");
713 QtObservedAtom::ptr walker = iter->second;
714 const ObservedValue_Index_t walkerid = walker->getIndex();
715 LOG(4, "DEBUG: GLWorldScene: Received signal moleculeChanged for atom "+toString(walkerid)+".");
716 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(walkerid);
717 ASSERT( parentiter != AtomNodeParentMap.left.end(),
718 "GLWorldScene::reparentAtom() - could not find object to id "+toString(walkerid));
719
720 // change parent entry
721 AtomNodeParentMap.left.erase(parentiter);
722 if (walker->getMoleculeRef() != NULL)
723 AtomNodeParentMap.left.insert( std::make_pair(walkerid, walker->getMoleculeRef()->getIndex()) );
724 else
725 AtomNodeParentMap.left.insert( std::make_pair(walkerid, (ObservedValue_Index_t)NULL) );
726 parentiter = AtomNodeParentMap.left.find(walkerid);
727
728 const AtomNodeMap::iterator atomiter = AtomsinSceneMap.find(walkerid);
729 if (atomiter != AtomsinSceneMap.end())
730 resetParent(atomiter->second, getMoleculeObject(parentiter->second));
731 // else atom does not yet exist
732
733 // check whether node is still shown, otherwise remove completely
734 checkAndRemoveAtom( walkerid );
735}
736
737/** Changes the parent of an left-side bond in the scene.
738 *
739 */
740void GLWorldScene::reparentBondLeft()
741{
742 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
743 QObject * origin = sender();
744 if (origin == NULL) {
745 ELOG(1, "Got reparentBondLeft() with sender being NULL.");
746 return;
747 }
748 ObservedBonds_t::const_iterator iter = ObservedBonds.find(origin);
749 ASSERT( iter != ObservedBonds.end(),
750 "GLWorldScene::reparentBondLeft() - bond "+toString(origin)+" is no longer stored?");
751 QtObservedBond::ptr bond = iter->second;
752 LOG(3, "INFO: GLWorldScene::reparentBondLeft() - Reparenting left side of bond "
753 << bond->getBondIndex() << ".");
754 reparentBond(bond, bond->getLeftAtom(), GLMoleculeObject_bond::left);
755
756 // check whether node is still shown, otherwise remove completely
757 checkAndRemoveBond( bond->getIndex() );
758}
759
760/** Changes the parent of an right-side bond in the scene.
761 *
762 */
763void GLWorldScene::reparentBondRight()
764{
765 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
766 QObject * origin = sender();
767 if (origin == NULL) {
768 ELOG(1, "Got reparentBondRight() with sender being NULL.");
769 return;
770 }
771 ObservedBonds_t::const_iterator iter = ObservedBonds.find(origin);
772 ASSERT( iter != ObservedBonds.end(),
773 "GLWorldScene::reparentBondRight() - bond "+toString(origin)+" is no longer stored?");
774 QtObservedBond::ptr bond = iter->second;
775 LOG(3, "INFO: GLWorldScene::reparentBondRight() - Reparenting right side of bond "
776 << bond->getBondIndex() << ".");
777 reparentBond(bond, bond->getRightAtom(), GLMoleculeObject_bond::right);
778
779 // check whether node is still shown, otherwise remove completely
780 checkAndRemoveBond( bond->getIndex() );
781}
782
783GLMoleculeObject_bond *GLWorldScene::getBondInScene(
784 const ObservedValue_Index_t _bondid,
785 GLMoleculeObject_bond::SideOfBond _side) const
786{
787 std::pair<GLWorldScene::BondNodeMap::const_iterator, GLWorldScene::BondNodeMap::const_iterator> iters =
788 BondsinSceneMap.equal_range(_bondid);
789 ASSERT( std::distance(iters.first, iters.second) >= 1,
790 "GLWorldScene::getBondInScene() - not at least one bond of id "
791 +toString(_bondid)+" present in scene.");
792 for (GLWorldScene::BondNodeMap::const_iterator bonditer = iters.first;
793 bonditer != iters.second; ++bonditer) {
794 if (bonditer->second->BondSide == _side)
795 return bonditer->second;
796 }
797 return NULL;
798}
799
800/** Changes the parent of an object in the scene.
801 *
802 * \param _atom atom of bond whose molecule we are associated to
803 * \param _side side of bond
804 */
805void GLWorldScene::reparentBond(
806 const QtObservedBond::ptr _bond,
807 const QtObservedAtom::ptr _atom,
808 const GLMoleculeObject_bond::SideOfBond _side)
809{
810 boost::recursive_mutex::scoped_lock lock(Bond_mutex);
811 const size_t dim = (_side == GLMoleculeObject_bond::left) ? 0 : 1;
812 const ObservedValue_Index_t bondid = _bond->getIndex();
813 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[dim].left.find(bondid);
814 ASSERT( parentiter != BondNodeParentMaps[dim].left.end(),
815 "GLWorldScene::reparentBond() - could not find object to id "+toString(bondid));
816
817 // change parent entry
818 BondNodeParentMaps[dim].left.erase(bondid);
819 if ((_atom != NULL) && (_atom->getMoleculeRef() != NULL))
820 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, _atom->getMoleculeRef()->getIndex()));
821 else
822 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, (ObservedValue_Index_t)NULL) );
823 parentiter = BondNodeParentMaps[dim].left.find(bondid);
824 LOG(3, "INFO: GLWorldScene::reparentBond() - Reparented bond "
825 << _bond->getBondIndex() << " to " << parentiter->second);
826
827 // reset parent
828 resetParent(getBondInScene(bondid, _side), getMoleculeObject(parentiter->second));
829}
830
831/** Resets the parent of an GLMoleculeObject.
832 *
833 * \param _obj object to reparent
834 * \param _molid index of parent molecule
835 */
836void GLWorldScene::resetParent(
837 GLMoleculeObject *_obj,
838 GLMoleculeObject_molecule *_molobj)
839{
840 if (_obj != NULL) {
841 if (_molobj != NULL) {
842 LOG(5, "DEBUG: Resetting parent of " << _obj << " to " << _molobj);
843 _obj->setParent(_molobj);
844 ASSERT( _obj->parent() == _molobj,
845 "GLWorldScene::resetParent() - new parent "+toString(_molobj)+" was not set.");
846 } else {
847 LOG(5, "DEBUG: Resetting parent of " << _obj << " to " << this);
848 _obj->setParent(this);
849 ASSERT( _obj->parent() == this,
850 "GLWorldScene::resetParent() - new parent "+toString(this)+" was not set.");
851 }
852 } else
853 ELOG(1, "Object to reparent was NULL.");
854 // else object does not yet exist
855}
856
857/** Adds a shape to the scene.
858 *
859 */
860void GLWorldScene::addShape(const std::string &_name)
861{
862 Shape * const shape = ShapeRegistry::getInstance().getByName(_name);
863 if (shape != NULL) {
864 GLMoleculeObject_shape *shapeObject = new GLMoleculeObject_shape(*shape, this);
865 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
866 ASSERT(iter == ShapesinSceneMap.end(),
867 "GLWorldScene::addShape() - same shape "+_name+" added again.");
868 ShapesinSceneMap.insert( make_pair(_name, shapeObject) );
869 } else
870 ELOG(2, "GLWorldScene::addShape() - shape disappeared before we could draw it.");
871
872 emit changed();
873}
874
875void GLWorldScene::removeShape(const std::string &_name)
876{
877 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
878 ASSERT(iter != ShapesinSceneMap.end(),
879 "GLWorldScene::removeShape() - shape "+_name+" not in scene.");
880 ShapesinSceneMap.erase(iter);
881 delete(iter->second);
882
883 emit changed();
884}
885
886void GLWorldScene::updateSelectedShapes()
887{
888 foreach (QObject *obj, children()) {
889 GLMoleculeObject_shape *shapeobj = qobject_cast<GLMoleculeObject_shape *>(obj);
890 if (shapeobj){
891 shapeobj->enable(ShapeRegistry::getInstance().isSelected(shapeobj->getShape()));
892 }
893 }
894
895 emit changed();
896}
897
898void GLWorldScene::initialize(QGLView *view, QGLPainter *painter) const
899{
900 // Initialize all of the mesh objects that we have as children.
901 foreach (QObject *obj, children()) {
902 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
903 if (meshobj)
904 meshobj->initialize(view, painter);
905 }
906}
907
908void GLWorldScene::draw(QGLPainter *painter, const QVector4D &cameraPlane) const
909{
910 // Draw all of the mesh objects that we have as children.
911 foreach (QObject *obj, children()) {
912 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
913 if (meshobj)
914 meshobj->draw(painter, cameraPlane);
915 }
916}
917
918void GLWorldScene::setSelectionMode(SelectionModeType mode)
919{
920 selectionMode = mode;
921 // TODO send update to toolbar
922}
923
924void GLWorldScene::setSelectionModeAtom()
925{
926 setSelectionMode(SelectAtom);
927}
928
929void GLWorldScene::setSelectionModeMolecule()
930{
931 setSelectionMode(SelectMolecule);
932}
933
Note: See TracBrowser for help on using the repository browser.