source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_molecule.cpp@ 739ee9

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 739ee9 was 739ee9, checked in by Frederik Heber <heber@…>, 10 years ago

GLMoleculeObject have m_visible, settable in QtMoleculeList.

  • is connected via QtMainWindow an GLWorldView, GLWorldScene.
  • i.e. molecule's atoms and bond display can now be switched on and off.
  • Property mode set to 100644
File size: 14.4 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
44#include "CodePatterns/MemDebug.hpp"
45
46#include "CodePatterns/Assert.hpp"
47#include "CodePatterns/Log.hpp"
48#include "CodePatterns/Observer/Notification.hpp"
49#include "CodePatterns/Observer/ObserverLog.hpp"
50
51#include "Atom/atom.hpp"
52#include "molecule.hpp"
53#include "Descriptors/AtomIdDescriptor.hpp"
54#include "Element/element.hpp"
55#include "LinearAlgebra/Vector.hpp"
56#include "World.hpp"
57
58#include "GLMoleculeObject_atom.hpp"
59
60GLMoleculeObject_molecule::GLMoleculeObject_molecule(QGLSceneNode *mesh[], QObject *parent, const molecule *molref) :
61 GLMoleculeObject(mesh, parent),
62 Observer(std::string("GLMoleculeObject_molecule")+toString(molref->getId())),
63 _molecule(molref),
64 hoverAtom(NULL)
65{
66 // sign on as observer (obtain non-const instance before)
67 _molecule->signOn(this, molecule::AtomInserted);
68 _molecule->signOn(this, molecule::AtomRemoved);
69 /*molref->signOn(this, AtomObservable::IndexChanged);
70 molref->signOn(this, AtomObservable::PositionChanged);
71 molref->signOn(this, AtomObservable::ElementChanged);
72 molref->signOn(this, AtomObservable::BondsAdded);*/
73 setMaterial(getMaterial(1));
74 World::getInstance().signOn(this, World::SelectionChanged);
75 updateBoundingBox();
76
77 // initially, atoms and bonds should be visible
78 m_visible = false;
79
80 init();
81}
82
83GLMoleculeObject_molecule::~GLMoleculeObject_molecule()
84{
85 _molecule->signOff(this, molecule::AtomInserted);
86 _molecule->signOff(this, molecule::AtomRemoved);
87 /*_atom->signOff(this, AtomObservable::IndexChanged);
88 _atom->signOff(this, AtomObservable::PositionChanged);
89 _atom->signOff(this, AtomObservable::ElementChanged);
90 _atom->signOff(this, AtomObservable::BondsAdded);*/
91 World::getInstance().signOff(this, World::SelectionChanged);
92}
93
94/** Initialise the WorldScene with molecules and atoms from World.
95 *
96 */
97void GLMoleculeObject_molecule::init()
98{
99 if (_molecule->begin() != _molecule->end()) {
100 for (molecule::const_iterator atomiter = _molecule->begin();
101 atomiter != _molecule->end();
102 atomiter++) {
103 // create atom objects in scene
104 atomInserted((*atomiter)->getId());
105
106 // create bond objects in scene
107 const BondList &bondlist = (*atomiter)->getListOfBonds();
108 for (BondList::const_iterator bonditer = bondlist.begin();
109 bonditer != bondlist.end();
110 ++bonditer) {
111 const bond::ptr _bond = *bonditer;
112 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == *atomiter) ?
113 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
114 bondInserted(_bond, side);
115 }
116 }
117 }
118}
119
120void GLMoleculeObject_molecule::addAtomBonds(
121 const bond::ptr &_bond,
122 const GLMoleculeObject_bond::SideOfBond _side
123 )
124{
125 bool bond_present = false;
126 const BondIds ids = getBondIds(_bond, _side);
127 // check whether bond is not present already
128 bond_present = BondsinSceneMap.count(ids);
129 if (!bond_present)
130 bondInserted(_bond, _side);
131 else {
132 BondsinSceneMap[ids]->resetPosition();
133 BondsinSceneMap[ids]->resetWidth();
134 }
135}
136
137void GLMoleculeObject_molecule::addAtomBonds(
138 const atom *_atom)
139{
140 const bool atom_present = AtomsinSceneMap.count(_atom->getId());
141 const BondList &bondlist = _atom->getListOfBonds();
142 for (BondList::const_iterator bonditer = bondlist.begin();
143 (bonditer != bondlist.end()) && atom_present;
144 ++bonditer) {
145 const bond::ptr _bond = *bonditer;
146 // check if OtherAtom's sphere is already present
147 const atom *OtherAtom = _bond->GetOtherAtom(_atom);
148 const bool otheratom_present = AtomsinSceneMap.count(OtherAtom->getId());
149 if (otheratom_present && atom_present) {
150 const GLMoleculeObject_bond::SideOfBond side = (_bond->leftatom == _atom) ?
151 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
152 const GLMoleculeObject_bond::SideOfBond otherside = (_bond->leftatom == _atom) ?
153 GLMoleculeObject_bond::right : GLMoleculeObject_bond::left;
154 addAtomBonds(_bond, side);
155 addAtomBonds(_bond, otherside);
156 }
157 }
158}
159
160void GLMoleculeObject_molecule::reinit()
161{
162 if (_molecule->getAtomCount() > 0) {
163 for (molecule::const_iterator atomiter = _molecule->begin();
164 atomiter != _molecule->end();
165 atomiter++) {
166 // check whether atom already exists
167 const atomId_t atomid = (*atomiter)->getId();
168 const bool atom_present = AtomsinSceneMap.count(atomid);
169 if (!atom_present)
170 atomInserted((*atomiter)->getId());
171 else
172 AtomsinSceneMap[atomid]->resetPosition();
173
174
175 // create bond objects in scene
176 addAtomBonds(*atomiter);
177 }
178 }
179}
180
181void GLMoleculeObject_molecule::updateBoundingBox()
182{
183 Shape shape = _molecule->getBoundingSphere();
184 Vector v = shape.getCenter();
185 setPosition(QVector3D(v[0], v[1], v[2]));
186 setScale(shape.getRadius() + 0.3); // getBoundingShape() only sees atoms as points, so make the box a bit bigger
187}
188
189void GLMoleculeObject_molecule::update(Observable *publisher)
190{
191#ifdef LOG_OBSERVER
192 const molecule *_mol = static_cast<molecule *>(publisher);
193 observerLog().addMessage() << "++ Update of Observer " << observerLog().getName(static_cast<Observer *>(this)) << " from molecule "+toString(_mol->getId())+".";
194#endif
195}
196
197void GLMoleculeObject_molecule::subjectKilled(Observable *publisher)
198{}
199
200void GLMoleculeObject_molecule::recieveNotification(Observable *publisher, Notification_ptr notification)
201{
202 if (publisher == dynamic_cast<const Observable*>(_molecule)){
203 // notofication from atom
204#ifdef LOG_OBSERVER
205 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
206 << " received notification from molecule " << _molecule->getId() << " for channel "
207 << notification->getChannelNo() << ".";
208#endif
209 switch (notification->getChannelNo()) {
210 case molecule::AtomInserted:
211 {
212 const atomId_t _id = _molecule->lastChanged()->getId();
213 #ifdef LOG_OBSERVER
214 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been inserted.";
215 #endif
216 atomInserted(_id);
217 break;
218 }
219 case World::AtomRemoved:
220 {
221 const atomId_t _id = _molecule->lastChanged()->getId();
222 #ifdef LOG_OBSERVER
223 observerLog().addMessage() << "++ Observer " << observerLog().getName(static_cast<Observer *>(this)) << " received notification that atom "+toString(_id)+" has been removed.";
224 #endif
225 atomRemoved(_id);
226 break;
227 }
228 default:
229 break;
230 }
231 }else{
232 // notification from world
233#ifdef LOG_OBSERVER
234 observerLog().addMessage() << "++ Update of Observer "<< observerLog().getName(static_cast<Observer *>(this))
235 << " received notification from world for channel "
236 << notification->getChannelNo() << ".";
237#endif
238 switch (notification->getChannelNo()) {
239 case World::SelectionChanged:
240 setSelected(World::getInstance().isSelected(_molecule));
241 break;
242 default:
243 break;
244 }
245 }
246}
247
248void GLMoleculeObject_molecule::initialize(QGLView *view, QGLPainter *painter)
249{
250 // Initialize all of the mesh objects that we have as children.
251// GLMoleculeObject::initialize(view, painter);
252 foreach (QObject *obj, children()) {
253 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
254 if (meshobj)
255 meshobj->initialize(view, painter);
256 }
257}
258
259void GLMoleculeObject_molecule::draw(QGLPainter *painter, const QVector4D &cameraPlane)
260{
261 // draw either molecule's mesh or all atoms and bonds
262 if (m_visible) {
263 GLMoleculeObject::draw(painter, cameraPlane);
264 } else {
265 // Draw all of the mesh objects that we have as children.
266 foreach (QObject *obj, children()) {
267 GLMoleculeObject *meshobj = qobject_cast<GLMoleculeObject *>(obj);
268 if (meshobj)
269 meshobj->draw(painter, cameraPlane);
270 }
271 }
272}
273
274/** Adds an atom of this molecule to the scene.
275 *
276 * @param _atom atom to add
277 */
278void GLMoleculeObject_molecule::atomInserted(const atomicNumber_t _id)
279{
280 LOG(3, "INFO: GLWorldScene: Received signal atomInserted for atom "+toString(_id)+".");
281 GLMoleculeObject_atom *atomObject = new GLMoleculeObject_atom(GLMoleculeObject::meshSphere, this, _id);
282 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
283 ASSERT(iter == AtomsinSceneMap.end(),
284 "GLWorldScene::atomAdded() - same atom with id "+toString(_id)+" added again.");
285 AtomsinSceneMap.insert( make_pair(_id, atomObject) );
286
287 qRegisterMetaType<atomId_t>("atomId_t");
288 qRegisterMetaType<bond::ptr>("bond::ptr");
289 qRegisterMetaType<GLMoleculeObject_bond::SideOfBond>("GLMoleculeObject_bond::SideOfBond");
290 connect (atomObject, SIGNAL(clicked(atomId_t)), this, SIGNAL(atomClicked(atomId_t)));
291 connect (atomObject, SIGNAL(changed()), this, SIGNAL(changed()));
292 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SIGNAL(changed()));
293 connect (atomObject, SIGNAL(hoverChanged(GLMoleculeObject *)), this, SLOT(hoverChangedSignalled(GLMoleculeObject *)));
294 connect (atomObject, SIGNAL(selectionChanged()), this, SIGNAL(changed()));
295 connect (atomObject, SIGNAL(BondsInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)), this, SLOT(bondInserted(const bond::ptr , const GLMoleculeObject_bond::SideOfBond)));
296 connect (atomObject, SIGNAL(indexChanged(GLMoleculeObject_atom*, int, int)), this, SIGNAL(changeAtomId(GLMoleculeObject_atom*, int, int)));
297
298 updateBoundingBox();
299
300 //bondsChanged(_atom);
301 emit changeOccured();
302}
303
304/** Removes an atom of this molecule from the scene.
305 *
306 * We just the id as the atom might have already been destroyed.
307 *
308 * @param _id id of atom to remove
309 */
310void GLMoleculeObject_molecule::atomRemoved(const atomicNumber_t _id)
311{
312 LOG(3, "INFO: GLWorldScene: Received signal atomRemoved for atom "+toString(_id)+".");
313 // bonds are removed by signal coming from ~bond
314 // remove atoms
315 AtomNodeMap::iterator iter = AtomsinSceneMap.find(_id);
316 ASSERT(iter != AtomsinSceneMap.end(),
317 "GLWorldScene::atomRemoved() - atom "+toString(_id)+" not on display.");
318 GLMoleculeObject_atom *atomObject = iter->second;
319 atomObject->disconnect();
320 AtomsinSceneMap.erase(iter);
321 delete atomObject;
322
323 updateBoundingBox();
324
325 emit changeOccured();
326}
327
328void GLMoleculeObject_molecule::hoverChangedSignalled(GLMoleculeObject *ob)
329{
330 // Find the atom, ob corresponds to.
331 hoverAtom = NULL;
332 GLMoleculeObject_atom *atomObject = dynamic_cast<GLMoleculeObject_atom *>(ob);
333 if (atomObject){
334 for (AtomNodeMap::iterator iter = AtomsinSceneMap.begin();iter != AtomsinSceneMap.end(); ++ iter){
335 if (iter->second == atomObject)
336 hoverAtom = World::getInstance().getAtom(AtomById(iter->first));
337 }
338 }
339
340 // Propagate signal.
341 emit hoverChanged(hoverAtom);
342}
343
344
345/** Helper function to get bond ids in the correct order for BondNodeMap.
346 *
347 * \return pair of ids in correct order.
348 */
349GLMoleculeObject_molecule::BondIds GLMoleculeObject_molecule::getBondIds(
350 const bond::ptr _bond,
351 const enum GLMoleculeObject_bond::SideOfBond _side)
352{
353 BondIds ids;
354 switch (_side) {
355 case GLMoleculeObject_bond::left:
356 ids = std::make_pair(_bond->leftatom->getId(), _bond->rightatom->getId());
357 break;
358 case GLMoleculeObject_bond::right:
359 ids = std::make_pair(_bond->rightatom->getId(), _bond->leftatom->getId());
360 break;
361 }
362 return ids;
363}
364
365/** Adds a bond to the scene.
366 *
367 * @param _bond bond to add
368 * @param side which side of the bond (left or right)
369 */
370void GLMoleculeObject_molecule::bondInserted(const bond::ptr _bond, const enum GLMoleculeObject_bond::SideOfBond _side)
371{
372 LOG(3, "INFO: GLWorldScene::bondInserted() - Adding bond "+toString(*_bond)+".");
373 //LOG(4, "INFO: Currently present bonds " << BondsinSceneMap << ".");
374
375 const BondIds ids = getBondIds(_bond, _side);
376 BondNodeMap::iterator iter = BondsinSceneMap.find(ids);
377 if (iter == BondsinSceneMap.end()) {
378 GLMoleculeObject_bond * bondObject =
379 new GLMoleculeObject_bond(GLMoleculeObject::meshCylinder, this, _bond, _side);
380 connect (
381 bondObject, SIGNAL(BondRemoved(const atomId_t, const atomId_t)),
382 this, SLOT(bondRemoved(const atomId_t, const atomId_t)));
383 connect (bondObject, SIGNAL(changed()), this, SIGNAL(changed()));
384 BondsinSceneMap.insert( make_pair(ids, bondObject) );
385 // BondIdsinSceneMap.insert( Leftids );
386 } else {
387 iter->second->resetPosition();
388 iter->second->resetWidth();
389 }
390 emit changeOccured();
391}
392
393/** Removes a bond from the scene.
394 *
395 * @param _bond bond to remove
396 */
397void GLMoleculeObject_molecule::bondRemoved(const atomId_t leftnr, const atomId_t rightnr)
398{
399 LOG(3, "INFO: GLWorldScene::bondRemoved() - Removing bond between "+toString(leftnr)+" and "+toString(rightnr)+".");
400 {
401 // left bond
402 const BondIds Leftids( make_pair(leftnr, rightnr) );
403 BondNodeMap::iterator leftiter = BondsinSceneMap.find( Leftids );
404 ASSERT(leftiter != BondsinSceneMap.end(),
405 "GLWorldScene::bondRemoved() - bond "+toString(leftnr)+"-"
406 +toString(rightnr)+" not on display.");
407 GLMoleculeObject_bond *bondObject = leftiter->second;
408 bondObject->disconnect();
409 BondsinSceneMap.erase(leftiter);
410 delete bondObject; // is done by signal from bond itself
411 //LOG(4, "INFO: Still present bonds " << BondsinSceneMap << ".");
412 }
413
414 emit changeOccured();
415}
416
417std::ostream &operator<<(std::ostream &ost, const GLMoleculeObject_molecule::BondIds &t)
418{
419 ost << t.first << "," << t.second;
420 return ost;
421}
Note: See TracBrowser for help on using the repository browser.