source: src/UIElements/Views/Qt4/Qt3D/GLMoleculeObject_atom.cpp@ 15c8a9

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 15c8a9 was 026bef, checked in by Frederik Heber <heber@…>, 9 years ago

Changed GLMoleculeObject_...:countSubjectKilled() to taking id parameter.

  • this is a precursor for when the ObservedValues reside with QtInstanceInformationBoard.
  • enhanced ObservedValue_wCallback to take a bound getIndex function().
  • additionally, we route internally to ObservedValue::get() and this gets us out of the painful situation where we need to supply an index getter to the ObservedValue that monitors the index (and hence must be present already to bind to its get function).
  • Property mode set to 100644
File size: 15.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 * GLMoleculeObject_atom.cpp
26 *
27 * Created on: Aug 17, 2011
28 * Author: heber
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "GLMoleculeObject_atom.hpp"
37
38#include <Qt3D/qglscenenode.h>
39
40#include "CodePatterns/MemDebug.hpp"
41
42#include "CodePatterns/Assert.hpp"
43#include "CodePatterns/Log.hpp"
44#include "CodePatterns/Observer/Notification.hpp"
45
46#include <algorithm>
47#include <boost/assign.hpp>
48
49#include "Atom/atom.hpp"
50#include "Bond/bond.hpp"
51#include "Descriptors/AtomIdDescriptor.hpp"
52#include "Element/element.hpp"
53#include "Element/periodentafel.hpp"
54#include "LinearAlgebra/Vector.hpp"
55#include "GLMoleculeObject_bond.hpp"
56#include "World.hpp"
57#include "WorldTime.hpp"
58
59#include "ObservedValue_wCallback.hpp"
60
61using namespace boost::assign;
62
63static const Observable::channels_t getAtomBondsChannels()
64{
65 Observable::channels_t channels;
66 channels += AtomObservable::BondsAdded, AtomObservable::BondsRemoved;
67 return channels;
68}
69
70// static entities
71const Observable::channels_t
72GLMoleculeObject_atom::AtomIndexChannels(1, AtomObservable::IndexChanged);
73const Observable::channels_t
74GLMoleculeObject_atom::AtomPositionChannels(1, AtomObservable::PositionChanged);
75const Observable::channels_t
76GLMoleculeObject_atom::AtomElementChannels(1, AtomObservable::ElementChanged);
77const Observable::channels_t
78GLMoleculeObject_atom::AtomBondsChannels(getAtomBondsChannels());
79
80GLMoleculeObject_atom::GLMoleculeObject_atom(
81 QGLSceneNode *mesh[],
82 QObject *parent,
83 const atomId_t _id) :
84 GLMoleculeObject(mesh, parent),
85 Observer(std::string("GLMoleculeObject_atom")+toString(_id)),
86 atomref(getAtom(_id)),
87 ObservedValues(MAX_ObservedTypes),
88 subjectKilledCount(0),
89 owner(NULL)
90{
91 boost::function<void(const atomId_t)> subjectKilled =
92 boost::bind(&GLMoleculeObject_atom::countsubjectKilled, this, _id);
93 initObservedValues(ObservedValues, _id, atomref, subjectKilled);
94
95 init(_id);
96}
97
98GLMoleculeObject_atom::GLMoleculeObject_atom(
99 QGLSceneNode *mesh[],
100 QObject *parent,
101 const atomId_t _id,
102 std::vector<boost::any> _ObservedValues) :
103 GLMoleculeObject(mesh, parent),
104 Observer(std::string("GLMoleculeObject_atom")+toString(_id)),
105 atomref(getAtom(_id)),
106 ObservedValues(_ObservedValues),
107 subjectKilledCount(0),
108 owner(NULL)
109{
110 init(_id);
111}
112
113void GLMoleculeObject_atom::init(const atomId_t _id)
114{
115 setObjectId(_id);
116 resetPosition();
117 resetElement();
118
119 m_selected = const_cast<const World &>(World::getInstance()).isAtomSelected(_id);
120
121 // sign On
122 activateObserver();
123
124 // atomref is only used for caching the ref, it must be used elswhere
125 const_cast<atom *&>(atomref) = NULL;
126
127 connect( this, SIGNAL(clicked()), this, SLOT(wasClicked()));
128 connect( this, SIGNAL(idChanged()), this, SLOT(resetIndex()), Qt::QueuedConnection);
129 connect( this, SIGNAL(elementChanged()), this, SLOT(resetElement()), Qt::QueuedConnection);
130 connect( this, SIGNAL(positionChanged()), this, SLOT(resetPosition()), Qt::QueuedConnection);
131 connect( this, SIGNAL(bondsChanged()), this, SLOT(resetPosition()), Qt::QueuedConnection);
132}
133
134void GLMoleculeObject_atom::activateObserver()
135{
136 if (atomref != NULL) {
137 owner = static_cast<const Observable *>(atomref);
138 owner->signOn(this, AtomObservable::IndexChanged);
139 owner->signOn(this, AtomObservable::PositionChanged);
140 owner->signOn(this, AtomObservable::ElementChanged);
141 owner->signOn(this, AtomObservable::BondsAdded);
142 owner->signOn(this, AtomObservable::BondsRemoved);
143 }
144}
145
146
147void GLMoleculeObject_atom::deactivateObserver()
148{
149 // sign Off
150 if (owner != NULL) {
151 owner->signOff(this, AtomObservable::IndexChanged);
152 owner->signOff(this, AtomObservable::PositionChanged);
153 owner->signOff(this, AtomObservable::ElementChanged);
154 owner->signOff(this, AtomObservable::BondsAdded);
155 owner->signOff(this, AtomObservable::BondsRemoved);
156 owner = NULL;
157 }
158}
159
160GLMoleculeObject_atom::~GLMoleculeObject_atom()
161{
162 deactivateObserver();
163 destroyObservedValues(ObservedValues);
164}
165
166void GLMoleculeObject_atom::resetIndex()
167{
168 const atomId_t newId = getAtomIndex();
169 const size_t oldId = objectId();
170 ASSERT( newId != oldId,
171 "GLMoleculeObject_atom::updateIndex() - index "+toString(newId)+" did not change.");
172 LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new index is "+toString(newId)+".");
173 setObjectId(newId);
174
175 emit indexChanged(this, oldId, newId);
176}
177
178void GLMoleculeObject_atom::resetPosition()
179{
180 const Vector Position = getAtomPosition();
181 LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new position is "+toString(Position)+".");
182 setPosition(QVector3D(Position[0], Position[1], Position[2]));
183}
184
185void GLMoleculeObject_atom::resetElement()
186{
187 size_t elementno = 0;
188 const element * const _type = World::getInstance().
189 getPeriode()->FindElement(getAtomElement());
190 if (_type != NULL) {
191 elementno = _type->getAtomicNumber();
192 } else { // if no element yet, set to hydrogen
193 elementno = 1;
194 }
195 LOG(4, "INFO: GLMoleculeObject_atom::resetIndex() - new element number is "+toString(elementno)+".");
196
197 // set materials
198 QGLMaterial *elementmaterial = getMaterial(elementno);
199 ASSERT(elementmaterial != NULL,
200 "GLMoleculeObject_atom::GLMoleculeObject_atom() - QGLMaterial ref from getter function is NULL.");
201 setMaterial(elementmaterial);
202
203 // set scale
204 double radius = 0.;
205 if (_type != NULL) {
206 radius = _type->getVanDerWaalsRadius();
207 } else {
208 radius = 0.5;
209 }
210 setScale( radius / 4. );
211}
212
213void GLMoleculeObject_atom::resetBonds()
214{
215 ListOfBonds_t ListOfBonds_new = getAtomBonds();
216 std::sort(ListOfBonds_new.begin(), ListOfBonds_new.end());
217 ListOfBonds_t BondsToAdd;
218 std::set_difference(
219 ListOfBonds_new.begin(), ListOfBonds_new.end(),
220 ListOfBonds.begin(), ListOfBonds.end(),
221 std::back_inserter(BondsToAdd));
222 ListOfBonds_t BondsToRemove;
223 std::set_difference(
224 ListOfBonds.begin(), ListOfBonds.end(),
225 ListOfBonds_new.begin(), ListOfBonds_new.end(),
226 std::back_inserter(BondsToRemove));
227 for (ListOfBonds_t::const_iterator iter = BondsToAdd.begin();
228 iter != BondsToAdd.end();
229 ++iter) {
230 const GLMoleculeObject_bond::SideOfBond side = (iter->first == getAtomIndex()) ?
231 GLMoleculeObject_bond::left : GLMoleculeObject_bond::right;
232 emit BondsAdded(iter->first, iter->second, side);
233 }
234 for (ListOfBonds_t::const_iterator iter = BondsToRemove.begin();
235 iter != BondsToRemove.end();
236 ++iter) {
237 emit BondsRemoved(iter->first, iter->second);
238 }
239 ListOfBonds = ListOfBonds_new;
240}
241
242void GLMoleculeObject_atom::Selected()
243{
244 ASSERT( !m_selected,
245 "GLMoleculeObject_atom::Selected() - 3D rep of atom is already selected.");
246 m_selected = true;
247
248 emit changed();
249}
250
251void GLMoleculeObject_atom::Unselected()
252{
253 ASSERT( m_selected,
254 "GLMoleculeObject_atom::Unselected() - 3D rep of atom is already unselected.");
255 m_selected = false;
256
257 emit changed();
258}
259
260
261void GLMoleculeObject_atom::draw(QGLPainter *painter, const QVector4D &cameraPlane)
262{
263 // call old hook to do the actual paining
264 GLMoleculeObject::draw(painter, cameraPlane);
265}
266
267void GLMoleculeObject_atom::wasClicked()
268{
269 LOG(4, "INFO: GLMoleculeObject_atom: atom " << getAtomIndex() << " has been clicked");
270 emit clicked(getAtomIndex());
271}
272
273const atom * const GLMoleculeObject_atom::getAtomConst(const atomId_t _id)
274{
275 const atom * const _atom = const_cast<const World &>(World::getInstance()).
276 getAtom(AtomById(_id));
277 return _atom;
278}
279
280atom * const GLMoleculeObject_atom::getAtom(const atomId_t _id)
281{
282 atom * const _atom = World::getInstance().getAtom(AtomById(_id));
283 return _atom;
284}
285
286atomId_t GLMoleculeObject_atom::updateIndex()
287{
288 return const_cast<const World &>(World::getInstance()).lastChangedAtomId();
289}
290
291Vector GLMoleculeObject_atom::updatePosition(
292 const boost::function<const atomId_t ()> &_getAtomIndex)
293{
294 const atom * const _atom = getAtomConst(_getAtomIndex());
295 if (_atom != NULL) {
296 return _atom->getPosition();
297 } else {
298 return zeroVec;
299 }
300}
301
302atomicNumber_t GLMoleculeObject_atom::updateElement(
303 const boost::function<const atomId_t ()> &_getAtomIndex)
304{
305 const atom * const _atom = getAtomConst(_getAtomIndex());
306 if (_atom != NULL) {
307 return _atom->getElementNo();
308 } else {
309 return (atomicNumber_t)-1;
310 }
311}
312
313GLMoleculeObject_atom::ListOfBonds_t GLMoleculeObject_atom::updateBonds(
314 const boost::function<const atomId_t ()> &_getAtomIndex)
315{
316 ListOfBonds_t ListOfBonds;
317 const atom * const _atom = getAtomConst(_getAtomIndex());
318 if (_atom != NULL) {
319 // make sure bonds is up-to-date
320 const BondList ListBonds = _atom->getListOfBonds();
321 for (BondList::const_iterator iter = ListBonds.begin();
322 iter != ListBonds.end();
323 ++iter)
324 ListOfBonds.insert( ListOfBonds.end(), std::make_pair(
325 (*iter)->leftatom->getId(),
326 (*iter)->rightatom->getId()) );
327 } else {
328 ELOG(2, "Atom with id "+toString(_getAtomIndex())+" is already gone.");
329 }
330 return ListOfBonds;
331}
332
333void GLMoleculeObject_atom::update(Observable *publisher)
334{
335 ASSERT(0, "GLMoleculeObject_atom::update() - we are not signed on for global updates.");
336}
337
338void GLMoleculeObject_atom::subjectKilled(Observable *publisher)
339{
340 deactivateObserver();
341
342 countsubjectKilled(getAtomIndex());
343}
344
345void GLMoleculeObject_atom::recieveNotification(Observable *publisher, Notification_ptr notification)
346{
347 // ObservedValues have been updated before, hence convert updates to Qt's signals
348 atom * const _atom = dynamic_cast<atom *>(publisher);
349 if (_atom != NULL) {
350 switch (notification->getChannelNo()) {
351 case AtomObservable::IndexChanged:
352 emit idChanged();
353 break;
354 case AtomObservable::PositionChanged:
355 emit positionChanged();
356 break;
357 case AtomObservable::ElementChanged:
358 emit elementChanged();
359 break;
360 case AtomObservable::BondsAdded:
361 case AtomObservable::BondsRemoved:
362 emit bondsChanged();
363 break;
364 default:
365 ASSERT(0, "GLMoleculeObject_atom::recieveNotification() - we are not signed on to channel "
366 +toString(notification->getChannelNo())+" of the atom.");
367 break;
368 }
369 } else
370 ASSERT(0, "GLMoleculeObject_atom::recieveNotification() - received notification from unexpected source.");
371}
372
373void GLMoleculeObject_atom::countsubjectKilled(const atomId_t)
374{
375 ++subjectKilledCount;
376
377 if (subjectKilledCount > ObservedValues.size())
378 emit InstanceRemoved(getAtomIndex());
379}
380
381void GLMoleculeObject_atom::initObservedValues(
382 std::vector<boost::any> &_ObservedValues,
383 const atomId_t _id,
384 const atom * const _atomref,
385 const boost::function<void(const atomId_t)> &_subjectKilled)
386{
387 /* This is an old note from when the code was still part of cstor's initializer body.
388 * TODO: Probably does not apply anymore but has not yet been tested.
389 *
390 * We must not use boost::cref(this) as "this" has not been properly constructed and seemingly
391 * boost::cref tries to do some magic to grasp the inheritance hierarchy which fails because
392 * the class has not been fully constructed yet. "This" itself seems to be working fine.
393 */
394
395 ASSERT( _ObservedValues.size() == MAX_ObservedTypes,
396 "GLMoleculeObject_atom::initObservedValues() - given ObservedValues has not correct size.");
397
398 // fill ObservedValues: index first
399 const boost::function<atomId_t ()> AtomIndexUpdater(
400 boost::bind(&GLMoleculeObject_atom::updateIndex));
401
402 ObservedValue_wCallback<atomId_t> * const IndexObservable =
403 new ObservedValue_wCallback<atomId_t>(
404 _atomref,
405 boost::bind(&GLMoleculeObject_atom::updateIndex),
406 "AtomIndex_"+toString(_id),
407 _id,
408 AtomIndexChannels,
409 _subjectKilled);
410 _ObservedValues[AtomIndex] = IndexObservable;
411
412 const boost::function<const atomId_t ()> AtomIndexGetter =
413 boost::bind(&ObservedValue_wCallback<atomId_t>::get,
414 IndexObservable);
415
416 // fill ObservedValues: then all the other that need index
417 const boost::function<Vector ()> AtomPositionUpdater(
418 boost::bind(&GLMoleculeObject_atom::updatePosition, AtomIndexGetter));
419 const boost::function<atomicNumber_t ()> AtomElementUpdater(
420 boost::bind(&GLMoleculeObject_atom::updateElement, AtomIndexGetter));
421 const boost::function<ListOfBonds_t ()> AtomBondsUpdater(
422 boost::bind(&GLMoleculeObject_atom::updateBonds, AtomIndexGetter));
423
424 _ObservedValues[AtomPosition] = new ObservedValue_wCallback<Vector, atomId_t>(
425 _atomref,
426 AtomPositionUpdater,
427 "AtomPosition_"+toString(_id),
428 AtomPositionUpdater(),
429 AtomPositionChannels,
430 _subjectKilled,
431 AtomIndexGetter);
432 _ObservedValues[AtomElement] = new ObservedValue_wCallback<atomicNumber_t, atomId_t>(
433 _atomref,
434 AtomElementUpdater,
435 "AtomElement"+toString(_id),
436 AtomElementUpdater(),
437 AtomElementChannels,
438 _subjectKilled,
439 AtomIndexGetter);
440 _ObservedValues[AtomBonds] = new ObservedValue_wCallback<ListOfBonds_t, atomId_t>(
441 _atomref,
442 AtomBondsUpdater,
443 "AtomBonds_"+toString(_id),
444 AtomBondsUpdater(),
445 AtomBondsChannels,
446 _subjectKilled,
447 AtomIndexGetter);
448}
449
450void GLMoleculeObject_atom::destroyObservedValues(
451 std::vector<boost::any> &_ObservedValues)
452{
453 delete boost::any_cast<ObservedValue_wCallback<atomId_t> *>(_ObservedValues[AtomIndex]);
454 delete boost::any_cast<ObservedValue_wCallback<Vector, atomId_t> *>(_ObservedValues[AtomPosition]);
455 delete boost::any_cast<ObservedValue_wCallback<atomicNumber_t, atomId_t> *>(_ObservedValues[AtomElement]);
456 delete boost::any_cast<ObservedValue_wCallback<ListOfBonds_t, atomId_t> *>(_ObservedValues[AtomBonds]);
457 _ObservedValues.clear();
458}
459
460atomId_t GLMoleculeObject_atom::getAtomIndex() const
461{
462 return boost::any_cast<ObservedValue_wCallback<atomId_t> *>(ObservedValues[AtomIndex])->get();
463}
464
465Vector GLMoleculeObject_atom::getAtomPosition() const
466{
467 return boost::any_cast<ObservedValue_wCallback<Vector, atomId_t> *>(ObservedValues[AtomPosition])->get();
468}
469
470atomicNumber_t GLMoleculeObject_atom::getAtomElement() const
471{
472 return boost::any_cast<ObservedValue_wCallback<atomicNumber_t, atomId_t> *>(ObservedValues[AtomElement])->get();
473}
474
475GLMoleculeObject_atom::ListOfBonds_t GLMoleculeObject_atom::getAtomBonds() const
476{
477 return boost::any_cast<ObservedValue_wCallback<ListOfBonds_t, atomId_t> *>(ObservedValues[AtomBonds])->get();
478}
Note: See TracBrowser for help on using the repository browser.