source: src/UIElements/Views/Qt4/Qt3D/GLWorldScene.cpp@ 375bc3f

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

GLWorldScene can now reparent atoms and bonds whose molecule is instantiated later.

  • parent maps are now bimaps.
  • Property mode set to 100644
File size: 24.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
76GLWorldScene::GLWorldScene(
77 QtObservedInstanceBoard * _board,
78 QObject *parent) :
79 QObject(parent),
80 BondNodeParentMaps(std::vector<BondNodeParentMap_t>(2)),
81 selectionMode(SelectAtom),
82 board(_board)
83{
84 qRegisterMetaType<atomId_t>("atomId_t");
85 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
86
87 int sphereDetails[] = {5, 3, 2, 0};
88 int cylinderDetails[] = {16, 8, 6, 3};
89 for (int i=0;i<GLMoleculeObject::DETAILTYPES_MAX;i++){
90 QGLBuilder emptyBuilder;
91 GLMoleculeObject::meshEmpty[i] = emptyBuilder.finalizedSceneNode();
92 QGLBuilder sphereBuilder;
93 sphereBuilder << QGLSphere(2.0, sphereDetails[i]);
94 GLMoleculeObject::meshSphere[i] = sphereBuilder.finalizedSceneNode();
95 GLMoleculeObject::meshSphere[i]->setOption(QGLSceneNode::CullBoundingBox, true);
96 QGLBuilder cylinderBuilder;
97 cylinderBuilder << QGLCylinder(.25,.25,1.0,cylinderDetails[i]);
98 GLMoleculeObject::meshCylinder[i] = cylinderBuilder.finalizedSceneNode();
99 GLMoleculeObject::meshCylinder[i]->setOption(QGLSceneNode::CullBoundingBox, true);
100 }
101 connect(board, SIGNAL(moleculeInserted(QtObservedMolecule::ptr)),
102 this, SLOT(insertMolecule(QtObservedMolecule::ptr)));
103 connect(board, SIGNAL(moleculeRemoved(ObservedValue_Index_t)),
104 this, SLOT(removeMolecule(ObservedValue_Index_t)));
105
106 connect(board, SIGNAL(atomInserted(QtObservedAtom::ptr)),
107 this, SLOT(connectAtom(QtObservedAtom::ptr)), Qt::DirectConnection);
108 connect(this, SIGNAL(atomConnected(QtObservedAtom::ptr)),
109 this, SLOT(insertAtom(QtObservedAtom::ptr)));
110 connect(board, SIGNAL(atomRemoved(ObservedValue_Index_t)),
111 this, SLOT(removeAtom(ObservedValue_Index_t)));
112
113 connect(board, SIGNAL(bondInserted(QtObservedBond::ptr)),
114 this, SLOT(connectBond(QtObservedBond::ptr)), Qt::DirectConnection);
115 connect(this, SIGNAL(bondConnected(QtObservedBond::ptr)),
116 this, SLOT(insertBond(QtObservedBond::ptr)));
117 connect(board, SIGNAL(bondRemoved(ObservedValue_Index_t)),
118 this, SLOT(removeBond(ObservedValue_Index_t)));
119
120// connect(this, SIGNAL(updated()), this, SLOT(update()));
121}
122
123GLWorldScene::~GLWorldScene()
124{
125 // remove all elements
126 GLMoleculeObject::cleanMaterialMap();
127}
128
129void GLWorldScene::clickAtom(atomId_t no)
130{
131 LOG(3, "INFO: GLWorldScene - atom " << no << " has been clicked.");
132 const atom * const Walker = const_cast<const World &>(World::getInstance()).
133 getAtom(AtomById(no));
134 ASSERT( Walker != NULL,
135 "GLWorldScene::clickAtom() - clicked atom has disappeared.");
136 if (selectionMode == SelectAtom){
137 if (!World::getInstance().isSelected(Walker))
138 SelectionAtomById(std::vector<atomId_t>(1,no));
139 else
140 SelectionNotAtomById(std::vector<atomId_t>(1,no));
141 }else if (selectionMode == SelectMolecule){
142 const molecule *mol = Walker->getMolecule();
143 ASSERT(mol, "Atom without molecule has been clicked.");
144 molids_t ids(1, mol->getId());
145 if (!World::getInstance().isSelected(mol))
146 SelectionMoleculeById(ids);
147 else
148 SelectionNotMoleculeById(ids);
149 }
150 emit clicked(no);
151}
152
153/** Prepares adding an atom to the scene
154 *
155 * We need to listen to moleculeChanged() in order to properly re-parent()
156 * this QObject
157 *
158 * @param _atom atom to connect
159 */
160void GLWorldScene::connectAtom(QtObservedAtom::ptr _atom)
161{
162 connect(_atom.get(), SIGNAL(moleculeChanged()), this, SLOT(reparentAtom()));
163
164 {
165 const ObservedValue_Index_t atomid = _atom->getIndex();
166 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
167 AtomNodeParentMap.left.insert( std::make_pair(atomid, (ObservedValue_Index_t)NULL) );
168 }
169
170 emit atomConnected(_atom);
171}
172
173/** Adds an atom to the scene.
174 *
175 * @param _atom atom to add
176 */
177void GLWorldScene::insertAtom(QtObservedAtom::ptr _atom)
178{
179 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "
180 << _atom->getAtomIndex());
181
182 const ObservedValue_Index_t atomid = _atom->getIndex();
183 QObject *parent = static_cast<QObject *>(this);
184 GLMoleculeObject_atom *atomObject = NULL;
185 {
186 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
187 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(atomid);
188 ASSERT (parentiter != AtomNodeParentMap.left.end(),
189 "GLWorldScene::insertAtom() - parent to atom id "+toString(atomid)+" unknown?");
190 const ObservedValue_Index_t parentindex = parentiter->second;
191 if (parentindex != (ObservedValue_Index_t)NULL) {
192 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentindex);
193 if (moliter != MoleculesinSceneMap.end())
194 parent = moliter->second;
195 }
196
197 atomObject = new GLMoleculeObject_atom(
198 GLMoleculeObject::meshSphere,
199 parent,
200 _atom);
201 ASSERT( atomObject != NULL,
202 "GLWorldScene::atomInserted - could not create atom object for "
203 +toString(_atom->getAtomIndex()));
204 }
205 AtomNodeMap::iterator iter = AtomsinSceneMap.find(atomid);
206 ASSERT(iter == AtomsinSceneMap.end(),
207 "GLWorldScene::insertAtom - same atom with id "
208 +toString(_atom->getAtomIndex())+" added again.");
209 AtomsinSceneMap.insert( make_pair(atomid, atomObject) );
210
211 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SLOT(clickAtom(atomId_t)));
212 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
213 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
214 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
215
216 emit changed();
217 emit changeOccured();
218}
219
220/** Removes an atom.
221 *
222 * @param _atomid index of the atom that is removed
223 */
224void GLWorldScene::removeAtom(ObservedValue_Index_t _atomid)
225{
226 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_atomid)+".");
227 // bonds are removed by signal coming from ~bond
228
229 // remove atoms
230 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_atomid);
231 ASSERT(iter != AtomsinSceneMap.end(),
232 "GLWorldScene::removeAtom() - atom "+toString(_atomid)+" not on display.");
233 GLMoleculeObject_atom *atomObject = iter->second;
234 AtomsinSceneMap.erase(iter);
235 delete atomObject;
236 {
237 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
238 AtomNodeParentMap.left.erase(_atomid);
239 }
240 emit changed();
241 emit changeOccured();
242}
243
244/** Prepares adding a bond to the scene
245 *
246 * We need to listen to moleculeChanged() in order to properly re-parent()
247 * this QObject
248 *
249 * @param _bond bond to connect
250 */
251void GLWorldScene::connectBond(QtObservedBond::ptr _bond)
252{
253 connect(_bond.get(), SIGNAL(leftmoleculeChanged()), this, SLOT(reparentBondLeft()));
254 connect(_bond.get(), SIGNAL(rightmoleculeChanged()), this, SLOT(reparentBondRight()));
255
256 {
257 const ObservedValue_Index_t bondid = _bond->getIndex();
258 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
259 if ((_bond->getLeftAtom() != NULL) && (_bond->getLeftAtom()->getMoleculeRef() != NULL))
260 BondNodeParentMaps[0].left.insert(
261 std::make_pair(bondid, _bond->getLeftAtom()->getMoleculeRef()->getIndex()) );
262 else
263 BondNodeParentMaps[0].left.insert(
264 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
265 if ((_bond->getRightAtom() != NULL) && (_bond->getRightAtom()->getMoleculeRef() != NULL))
266 BondNodeParentMaps[1].left.insert(
267 std::make_pair(bondid, _bond->getRightAtom()->getMoleculeRef()->getIndex()) );
268 else
269 BondNodeParentMaps[1].left.insert(
270 std::make_pair(bondid, (ObservedValue_Index_t)NULL) );
271 }
272
273 emit bondConnected(_bond);
274}
275
276/** Adds a bond to the scene.
277 *
278 * @param _bond bond to add
279 */
280void GLWorldScene::insertBond(QtObservedBond::ptr _bond)
281{
282 static const std::vector< GLMoleculeObject_bond::SideOfBond > bondsides =
283 boost::assign::list_of<GLMoleculeObject_bond::SideOfBond>
284 (GLMoleculeObject_bond::left)
285 (GLMoleculeObject_bond::right);
286 LOG(3, "INFO: GLWorldScene::insertBond() - Adding bonds " << _bond->getBondIndex());
287
288 const ObservedValue_Index_t bondid = _bond->getIndex();
289#ifdef NDEBUG
290 BondNodeMap::iterator iter = BondsinSceneMap.find(bondid);
291 ASSERT( iter == BondsinSceneMap.end(),
292 "GLWorldScene::insertBond() - bond "+toString(bondid)+" is already known.");
293#endif
294 {
295 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
296 for (size_t i=0;i<2;++i) {
297 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[i].left.find(bondid);
298 ASSERT (parentiter != BondNodeParentMaps[i].left.end(),
299 "GLWorldScene::insertBond() - parent to bond id "+toString(bondid)+" unknown?");
300 QObject *parent = this;
301 if (parentiter->second != (ObservedValue_Index_t)NULL) {
302 const MoleculeNodeMap::iterator moliter = MoleculesinSceneMap.find(parentiter->second);
303 if (moliter != MoleculesinSceneMap.end())
304 parent = moliter->second;
305 }
306
307 GLMoleculeObject_bond *bondObject = new GLMoleculeObject_bond(
308 GLMoleculeObject::meshCylinder,
309 parent,
310 _bond,
311 bondsides[i]);
312 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
313 BondsinSceneMap.insert( std::make_pair(bondid, bondObject) );
314 }
315 }
316
317 emit changed();
318 emit changeOccured();
319}
320
321/** Removes a bond.
322 *
323 * @param _bondid id of bond to remove
324 */
325void GLWorldScene::removeBond(ObservedValue_Index_t _bondid)
326{
327 LOG(3, "INFO: GLWorldScene::removedBond() - Removing bond to id " << _bondid);
328
329 // left bond
330 std::pair<BondNodeMap::iterator, BondNodeMap::iterator> iters =
331 BondsinSceneMap.equal_range(_bondid);
332 ASSERT( iters.first != iters.second,
333 "GLWorldScene::removedBond() - could not find bond to id "+toString(_bondid));
334 for (BondNodeMap::iterator iter = iters.first; iter != iters.second; ++iter) {
335 GLMoleculeObject_bond *bondObject = iter->second;
336 delete bondObject; // is done by signal from bond itself
337 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
338 }
339 BondsinSceneMap.erase(_bondid);
340 {
341 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
342 BondNodeParentMaps[0].left.erase(_bondid);
343 BondNodeParentMaps[1].left.erase(_bondid);
344 }
345
346 emit changed();
347 emit changeOccured();
348}
349
350void GLWorldScene::hoverChangedSignalled(GLMoleculeObject *ob)
351{
352 // Find the atom, ob corresponds to.
353 hoverAtomId = -1;
354 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
355 if (atomObject){
356 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
357 if (iter->second == atomObject)
358 hoverAtomId = iter->second->objectId();
359 }
360
361 // Propagate signal.
362 emit hoverChanged(hoverAtomId);
363 } else {
364 // Find the atom, ob corresponds to.
365 GLMoleculeObject_molecule *moleculeObject = dynamic_cast<GLMoleculeObject_molecule *>(ob);
366 if (moleculeObject){
367 // Propagate signal.
368 emit hoverChanged(moleculeObject->objectId(), 0);
369 }
370 }
371}
372
373void GLWorldScene::clickMolecule(moleculeId_t no)
374{
375 LOG(3, "INFO: GLMoleculeObject_molecule - mol " << no << " has been clicked.");
376 const molecule * const mol= const_cast<const World &>(World::getInstance()).
377 getMolecule(MoleculeById(no));
378 ASSERT(mol, "Atom without molecule has been clicked.");
379 molids_t ids(1, mol->getId());
380 if (!World::getInstance().isSelected(mol))
381 SelectionMoleculeById(ids);
382 else
383 SelectionNotMoleculeById(ids);
384 emit clicked(no);
385}
386
387/** Inserts a molecule into the scene.
388 *
389 * @param _mol molecule to insert
390 */
391void GLWorldScene::insertMolecule(QtObservedMolecule::ptr _mol)
392{
393 const ObservedValue_Index_t molid = _mol->getIndex();
394 LOG(3, "INFO: GLWorldScene: Received signal moleculeInserted for molecule "
395 << _mol->getMolIndex());
396
397 MoleculeNodeMap::const_iterator iter = MoleculesinSceneMap.find(molid);
398 ASSERT( iter == MoleculesinSceneMap.end(),
399 "GLWorldScene::insertMolecule() - molecule's id "+toString(molid)
400 +" already present.");
401
402 // add new object
403 LOG(1, "DEBUG: Adding GLMoleculeObject_molecule to id " << molid);
404 GLMoleculeObject_molecule *molObject =
405 new GLMoleculeObject_molecule(
406 GLMoleculeObject::meshEmpty,
407 this,
408 _mol);
409 ASSERT( molObject != NULL,
410 "GLWorldScene::insertMolecule - could not create molecule object for "
411 +toString(molid));
412
413 // check all atoms for not yet assigned parents
414 {
415 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
416 std::pair<AtomNodeParentMap_t::right_const_iterator, AtomNodeParentMap_t::right_const_iterator> iters =
417 AtomNodeParentMap.right.equal_range(molid);
418 for (AtomNodeParentMap_t::right_const_iterator iter = iters.first;
419 iter != iters.second; ++iter) {
420 AtomNodeMap::const_iterator atomiter = AtomsinSceneMap.find(iter->second);
421 if (atomiter != AtomsinSceneMap.end())
422 resetParent(atomiter->second, molObject);
423 }
424 }
425 // check all bonds for not yet assigned parents
426 {
427 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
428 for (size_t i=0;i<2;++i) {
429 std::pair<BondNodeParentMap_t::right_const_iterator, BondNodeParentMap_t::right_const_iterator> iters =
430 BondNodeParentMaps[i].right.equal_range(molid);
431 for (BondNodeParentMap_t::right_const_iterator iter = iters.first;
432 iter != iters.second; ++iter) {
433 BondNodeMap::const_iterator bonditer = BondsinSceneMap.find(iter->second);
434 if (bonditer != BondsinSceneMap.end())
435 resetParent(bonditer->second, molObject);
436 }
437 }
438 }
439
440#ifndef NDEBUG
441 std::pair<MoleculeNodeMap::iterator, bool> inserter =
442#endif
443 MoleculesinSceneMap.insert( make_pair(molid, molObject) );
444 ASSERT(inserter.second,
445 "GLWorldScene::insertMolecule() - molecule "+toString(_mol->getMolIndex())
446 +" already present in scene.");
447
448 connect (molObject, SIGNAL(changed()), this, SIGNAL(changed()));
449 connect (molObject, SIGNAL(changeOccured()), this, SIGNAL(changeOccured()));
450
451 emit changed();
452 emit changeOccured();
453}
454
455/** Removes a molecule from the scene.
456 *
457 * @param _molid index of the molecule to remove
458 */
459void GLWorldScene::removeMolecule(ObservedValue_Index_t _molid)
460{
461 LOG(3, "INFO: GLWorldScene: Received signal moleculeRemoved for molecule "+toString(_molid)+".");
462
463 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_molid);
464 ASSERT ( iter != MoleculesinSceneMap.end(),
465 "GLWorldScene::removeMolecule() - to be removed molecule "+toString(_molid)
466 +" is already gone.");
467 // check if it's already empty
468 GLMoleculeObject_molecule *molObject = iter->second;
469 delete molObject;
470 MoleculesinSceneMap.erase(iter);
471
472 emit changed();
473 emit changeOccured();
474}
475
476void GLWorldScene::moleculesVisibilityChanged(ObservedValue_Index_t _id, bool _visible)
477{
478 MoleculeNodeMap::iterator iter = MoleculesinSceneMap.find(_id);
479 ASSERT( iter != MoleculesinSceneMap.end(),
480 "GLWorldScene::moleculeInserted() - molecule's id "
481 +toString(board->getMoleculeIdToIndex(_id))+" is unknown.");
482
483 GLMoleculeObject_molecule *molObject = iter->second;
484 molObject->setVisible(_visible);
485
486 emit changed();
487 emit changeOccured();
488}
489
490/** This converts safely index into a GLMoleculeObject_molecule.
491 *
492 * \param _MoleculesinSceneMap all present molecules
493 * \param _molid index to look for
494 * \return MolObject or NULL when not found
495 */
496GLMoleculeObject_molecule *GLWorldScene::getMoleculeObject(
497 const ObservedValue_Index_t _molid) const
498{
499 const MoleculeNodeMap::const_iterator moliter = MoleculesinSceneMap.find(_molid);
500 if (moliter != MoleculesinSceneMap.end())
501 return moliter->second;
502 else
503 return NULL;
504}
505
506/** Changes the parent of an object in the scene.
507 *
508 * \param _id index of the object whose parent to change
509 * \param _ob new parent
510 */
511void GLWorldScene::reparentAtom()
512{
513 QtObservedAtom *walker = dynamic_cast<QtObservedAtom *>(sender());
514 boost::recursive_mutex::scoped_lock lock(AtomNodeParentMap_mutex);
515 const ObservedValue_Index_t walkerid = walker->getIndex();
516 AtomNodeParentMap_t::left_iterator parentiter = AtomNodeParentMap.left.find(walkerid);
517 ASSERT( parentiter != AtomNodeParentMap.left.end(),
518 "GLWorldScene::reparentAtom() - could not find object to id "+toString(walkerid));
519
520 // change parent entry
521 AtomNodeParentMap.left.erase(parentiter);
522 if (walker->getMoleculeRef() != NULL)
523 AtomNodeParentMap.left.insert( std::make_pair(walkerid, walker->getMoleculeRef()->getIndex()) );
524 else
525 AtomNodeParentMap.left.insert( std::make_pair(walkerid, (ObservedValue_Index_t)NULL) );
526 parentiter = AtomNodeParentMap.left.find(walkerid);
527
528 const AtomNodeMap::iterator atomiter = AtomsinSceneMap.find(walkerid);
529 if (atomiter != AtomsinSceneMap.end())
530 resetParent(atomiter->second, getMoleculeObject(parentiter->second));
531 // else atom does not yet exist
532}
533
534/** Changes the parent of an left-side bond in the scene.
535 *
536 */
537void GLWorldScene::reparentBondLeft()
538{
539 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
540 QtObservedBond *bond = dynamic_cast<QtObservedBond *>(sender());
541 reparentBond(bond, bond->getLeftAtom(), GLMoleculeObject_bond::left);
542}
543
544/** Changes the parent of an right-side bond in the scene.
545 *
546 */
547void GLWorldScene::reparentBondRight()
548{
549 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
550 QtObservedBond *bond = dynamic_cast<QtObservedBond *>(sender());
551 reparentBond(bond, bond->getRightAtom(), GLMoleculeObject_bond::right);
552}
553
554GLMoleculeObject_bond *GLWorldScene::getBondInScene(
555 const ObservedValue_Index_t _bondid,
556 GLMoleculeObject_bond::SideOfBond _side) const
557{
558 std::pair<GLWorldScene::BondNodeMap::const_iterator, GLWorldScene::BondNodeMap::const_iterator> iters =
559 BondsinSceneMap.equal_range(_bondid);
560 ASSERT( std::distance(iters.first, iters.second) == 2,
561 "GLWorldScene::getBondInScene() - not exactly two bonds of same id "
562 +toString(_bondid)+" present in scene.");
563 for (GLWorldScene::BondNodeMap::const_iterator bonditer = iters.first;
564 bonditer != iters.second; ++bonditer) {
565 if (bonditer->second->BondSide == _side)
566 return bonditer->second;
567 }
568 return NULL;
569}
570
571/** Changes the parent of an object in the scene.
572 *
573 * \param _atom atom of bond whose molecule we are associated to
574 * \param _side side of bond
575 */
576void GLWorldScene::reparentBond(
577 QtObservedBond *_bond,
578 const QtObservedAtom * const _atom,
579 const GLMoleculeObject_bond::SideOfBond _side)
580{
581 boost::recursive_mutex::scoped_lock lock(BondNodeParentMap_mutex);
582 const size_t dim = (_side == GLMoleculeObject_bond::left) ? 0 : 1;
583 const ObservedValue_Index_t bondid = _bond->getIndex();
584 BondNodeParentMap_t::left_iterator parentiter = BondNodeParentMaps[dim].left.find(bondid);
585 ASSERT( parentiter != BondNodeParentMaps[dim].left.end(),
586 "GLWorldScene::reparentBond() - could not find object to id "+toString(bondid));
587
588 // change parent entry
589 BondNodeParentMaps[dim].left.erase(bondid);
590 if ((_atom != NULL) && (_atom->getMoleculeRef() != NULL))
591 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, _atom->getMoleculeRef()->getIndex()));
592 else
593 BondNodeParentMaps[dim].left.insert( std::make_pair( bondid, (ObservedValue_Index_t)NULL) );
594 parentiter = BondNodeParentMaps[dim].left.find(bondid);
595
596 // reset parent
597 resetParent(getBondInScene(bondid, _side), getMoleculeObject(parentiter->second));
598}
599
600/** Resets the parent of an GLMoleculeObject.
601 *
602 * \param _obj object to reparent
603 * \param _molid index of parent molecule
604 */
605void GLWorldScene::resetParent(
606 GLMoleculeObject *_obj,
607 GLMoleculeObject_molecule *_molobj)
608{
609 if (_obj != NULL) {
610 QObject *parent = this;
611 if (_molobj != NULL)
612 parent = _molobj;
613 // else: molecule does not yet exist: is done when molecule is instantiated
614 _obj->setParent(parent);
615 }
616 // else object does not yet exist
617}
618
619/** Adds a shape to the scene.
620 *
621 */
622void GLWorldScene::addShape(const std::string &_name)
623{
624 Shape * const shape = ShapeRegistry::getInstance().getByName(_name);
625 if (shape != NULL) {
626 GLMoleculeObject_shape *shapeObject = new GLMoleculeObject_shape(*shape, this);
627 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
628 ASSERT(iter == ShapesinSceneMap.end(),
629 "GLWorldScene::addShape() - same shape "+_name+" added again.");
630 ShapesinSceneMap.insert( make_pair(_name, shapeObject) );
631 } else
632 ELOG(2, "GLWorldScene::addShape() - shape disappeared before we could draw it.");
633
634 emit changed();
635}
636
637void GLWorldScene::removeShape(const std::string &_name)
638{
639 ShapeNodeMap::iterator iter = ShapesinSceneMap.find(_name);
640 ASSERT(iter != ShapesinSceneMap.end(),
641 "GLWorldScene::removeShape() - shape "+_name+" not in scene.");
642 ShapesinSceneMap.erase(iter);
643 delete(iter->second);
644
645 emit changed();
646}
647
648void GLWorldScene::updateSelectedShapes()
649{
650 foreach (QObject *obj, children()) {
651 GLMoleculeObject_shape *shapeobj = qobject_cast<GLMoleculeObject_shape *>(obj);
652 if (shapeobj){
653 shapeobj->enable(ShapeRegistry::getInstance().isSelected(shapeobj->getShape()));
654 }
655 }
656
657 emit changed();
658}
659
660void GLWorldScene::initialize(QGLView *view, QGLPainter *painter) const
661{
662 // Initialize all of the mesh objects that we have as children.
663 foreach (QObject *obj, children()) {
664 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
665 if (meshobj)
666 meshobj->initialize(view, painter);
667 }
668}
669
670void GLWorldScene::draw(QGLPainter *painter, const QVector4D &cameraPlane) const
671{
672 // Draw all of the mesh objects that we have as children.
673 foreach (QObject *obj, children()) {
674 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
675 if (meshobj)
676 meshobj->draw(painter, cameraPlane);
677 }
678}
679
680void GLWorldScene::setSelectionMode(SelectionModeType mode)
681{
682 selectionMode = mode;
683 // TODO send update to toolbar
684}
685
686void GLWorldScene::setSelectionModeAtom()
687{
688 setSelectionMode(SelectAtom);
689}
690
691void GLWorldScene::setSelectionModeMolecule()
692{
693 setSelectionMode(SelectMolecule);
694}
695
Note: See TracBrowser for help on using the repository browser.