source: src/World.cpp@ bc58f2

Candidate_v1.7.1 stable
Last change on this file since bc58f2 was 25aa214, checked in by Frederik Heber <frederik.heber@…>, 11 days ago

FIX: fragmentation hydrogens do not trigger AtomInserted.

  • we had already switched off position and element changes. However, the fragmentation hydrogens could still be briefly seen on creation because the AtomInserted notification is still triggered. The World::createAtom allows now to suppress the notifcation. The switch options are put into an enum to make them very verbose in the code. This should really only be used by the HydrogenPool.
  • Property mode set to 100644
File size: 33.3 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 * World.cpp
26 *
27 * Created on: Feb 3, 2010
28 * Author: crueger
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36//#include "CodePatterns/MemDebug.hpp"
37
38#include "World.hpp"
39
40#include <functional>
41
42#include "Actions/ActionTrait.hpp"
43#include "Actions/ManipulateAtomsProcess.hpp"
44#include "Atom/atom.hpp"
45#include "Box.hpp"
46#include "CodePatterns/Assert.hpp"
47#include "config.hpp"
48#include "Descriptors/AtomDescriptor.hpp"
49#include "Descriptors/AtomDescriptor_impl.hpp"
50#include "Descriptors/AtomIdDescriptor.hpp"
51#include "Descriptors/AtomSelectionDescriptor.hpp"
52#include "Descriptors/MoleculeDescriptor.hpp"
53#include "Descriptors/MoleculeDescriptor_impl.hpp"
54#include "Descriptors/MoleculeIdDescriptor.hpp"
55#include "Descriptors/MoleculeSelectionDescriptor.hpp"
56#include "Descriptors/SelectiveConstIterator_impl.hpp"
57#include "Descriptors/SelectiveIterator_impl.hpp"
58#include "Element/periodentafel.hpp"
59#include "Fragmentation/Homology/HomologyContainer.hpp"
60#include "Graph/BondGraph.hpp"
61#include "Graph/DepthFirstSearchAnalysis.hpp"
62#include "Helpers/defs.hpp"
63#include "LinearAlgebra/RealSpaceMatrix.hpp"
64#include "LinkedCell/LinkedCell_Controller.hpp"
65#include "LinkedCell/PointCloudAdaptor.hpp"
66#include "molecule.hpp"
67#include "Thermostats/ThermoStatContainer.hpp"
68#include "WorldTime.hpp"
69
70#include "IdPool_impl.hpp"
71
72#include "CodePatterns/IteratorAdaptors.hpp"
73#include "CodePatterns/Singleton_impl.hpp"
74#include "CodePatterns/Observer/Channels.hpp"
75#include "CodePatterns/Observer/ObservedContainer_impl.hpp"
76
77using namespace MoleCuilder;
78
79/******************************* Notifications ************************/
80
81
82atom* World::_lastchangedatom = NULL;
83atomId_t World::_lastchangedatomid = -1;
84molecule* World::_lastchangedmol = NULL;
85moleculeId_t World::_lastchangedmolid = -1;
86
87/******************************* getter and setter ************************/
88periodentafel *&World::getPeriode()
89{
90 return periode;
91}
92
93BondGraph *&World::getBondGraph()
94{
95 return BG;
96}
97
98HomologyContainer &World::getHomologies()
99{
100 return *homologies;
101}
102
103void World::resetHomologies(HomologyContainer *&_homologies)
104{
105 HomologyContainer *oldhomologies = homologies;
106
107 // install new instance, resetting given pointer
108 homologies = _homologies;
109 _homologies = NULL;
110
111 // delete old instance which also informs all observers
112 delete oldhomologies;
113}
114
115void World::setBondGraph(BondGraph *_BG){
116 delete (BG);
117 BG = _BG;
118}
119
120config *&World::getConfig(){
121 return configuration;
122}
123
124// Atoms
125
126atom* World::getAtom(AtomDescriptor descriptor){
127 return descriptor.find();
128}
129
130const atom* World::getAtom(AtomDescriptor descriptor) const{
131 return const_cast<const AtomDescriptor &>(descriptor).find();
132}
133
134World::AtomComposite World::getAllAtoms(AtomDescriptor descriptor){
135 return descriptor.findAll();
136}
137
138World::ConstAtomComposite World::getAllAtoms(AtomDescriptor descriptor) const {
139 return const_cast<const AtomDescriptor &>(descriptor).findAll();
140}
141
142World::AtomComposite World::getAllAtoms(){
143 return getAllAtoms(AllAtoms());
144}
145
146World::ConstAtomComposite World::getAllAtoms() const {
147 return getAllAtoms(AllAtoms());
148}
149
150int World::numAtoms() const {
151 return atoms.size();
152}
153
154// Molecules
155
156molecule *World::getMolecule(MoleculeDescriptor descriptor){
157 return descriptor.find();
158}
159
160const molecule *World::getMolecule(MoleculeDescriptor descriptor) const {
161 return const_cast<const MoleculeDescriptor &>(descriptor).find();
162}
163
164std::vector<molecule*> World::getAllMolecules(MoleculeDescriptor descriptor){
165 return descriptor.findAll();
166}
167
168std::vector<const molecule*> World::getAllMolecules(MoleculeDescriptor descriptor) const {
169 return const_cast<const MoleculeDescriptor &>(descriptor).findAll();
170}
171
172std::vector<molecule*> World::getAllMolecules(){
173 return getAllMolecules(AllMolecules());
174}
175
176std::vector<const molecule*> World::getAllMolecules() const {
177 return getAllMolecules(AllMolecules());
178}
179
180int World::numMolecules() const {
181 return molecules.size();
182}
183
184// system
185
186Box& World::getDomain() {
187 return *cell_size;
188}
189
190void World::setDomain(const RealSpaceMatrix &mat){
191 OBSERVE;
192 *cell_size = mat;
193}
194
195void World::setDomain(double * matrix)
196{
197 OBSERVE;
198 RealSpaceMatrix M = ReturnFullMatrixforSymmetric(matrix);
199 cell_size->setM(M);
200}
201
202LinkedCell::LinkedCell_View World::getLinkedCell(double distance)
203{
204 ASSERT( distance >= 0,
205 "World::getLinkedCell() - distance is not positive.");
206 if (distance < 1.) {
207 ELOG(2, "Linked cell grid with length less than 1. is very memory-intense!");
208 distance = 1.;
209 }
210 // we have to grope past the ObservedContainer mechanism and transmorph the map
211 // into a traversable list for the adaptor
212 PointCloudAdaptor< AtomSet::set_t, MapValueIterator<AtomSet::set_t::iterator> > atomset(
213 &(atoms.getContent()),
214 std::string("WorldsAtoms"));
215 return LCcontroller->getView(distance, atomset);
216}
217
218const unsigned World::getTime() const
219{
220 return WorldTime::getTime();
221}
222
223static bool areBondsPresent(const unsigned int _step)
224{
225 bool status = false;
226
227 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
228 (!status) && (iter != const_cast<const World &>(World::getInstance()).atomEnd()); ++iter) {
229 const atom * const Walker = *iter;
230 status |= !Walker->getListOfBondsAtStep(_step).empty();
231 }
232
233 return status;
234}
235
236static bool areAtomsPresent(const unsigned int _step)
237{
238 bool status = false;
239
240 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
241 (!status) && (iter != const_cast<const World &>(World::getInstance()).atomEnd()); ++iter) {
242 const atom * const Walker = *iter;
243 status |= (Walker->getTrajectorySize() >= _step);
244 }
245
246 return status;
247}
248
249static void copyBondgraph(const unsigned int _srcstep, const unsigned int _deststep)
250{
251 // gather all bonds from _srcstep
252 std::set<bond *> SetOfBonds;
253 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
254 iter != const_cast<const World &>(World::getInstance()).atomEnd(); ++iter) {
255 const atom * const Walker = *iter;
256 const BondList bonds = Walker->getListOfBondsAtStep(_srcstep);
257 BOOST_FOREACH( bond::ptr bondptr, bonds) {
258 SetOfBonds.insert(bondptr.get());
259 }
260 }
261 LOG(4, "DEBUG: We gathered " << SetOfBonds.size() << " bonds in total.");
262
263 // copy bond to new time step
264 for (std::set<bond *>::const_iterator bonditer = SetOfBonds.begin();
265 bonditer != SetOfBonds.end(); ++bonditer) {
266 const atom * const Walker = (*bonditer)->leftatom;
267 const atom * const OtherWalker = (*bonditer)->rightatom;
268 bond::ptr const _bond =
269 const_cast<atom *>(Walker)->addBond(_deststep, const_cast<atom *>(OtherWalker));
270 _bond->setDegree((*bonditer)->getDegree());
271 }
272}
273
274//static void copyAtoms(const unsigned int _srcstep, const unsigned int _deststep)
275//{
276// for (World::AtomIterator iter = World::getInstance().getAtomIter();
277// iter != World::getInstance().atomEnd(); ++iter) {
278// atom * const Walker = *iter;
279// Walker->UpdateStep(_deststep);
280// Walker->setPositionAtStep(_deststep, Walker->getPositionAtStep(_srcstep));
281// Walker->setAtomicVelocityAtStep(_deststep, Walker->getAtomicVelocityAtStep(_srcstep));
282// Walker->setAtomicForceAtStep(_deststep, Walker->getAtomicForceAtStep(_srcstep));
283// }
284//}
285
286void World::setTime(const unsigned int _step)
287{
288 if (_step != WorldTime::getTime()) {
289 const unsigned int oldstep = WorldTime::getTime();
290
291// if (!areAtomsPresent(_step))
292// copyAtoms(oldstep, _step);
293
294 // 1. copy bond graph (such not each addBond causes GUI update)
295 if (!areBondsPresent(_step)) {
296// AtomComposite Set = getAllAtoms();
297// BG->cleanAdjacencyList(Set);
298 copyBondgraph(oldstep, _step);
299 }
300
301 // 2. set new time
302 WorldTime::getInstance().setTime(_step);
303
304 // 4. scan for connected subgraphs => molecules
305 DepthFirstSearchAnalysis DFS;
306 DFS();
307 DFS.UpdateMoleculeStructure();
308 }
309}
310
311std::string World::getDefaultName() {
312 return defaultName;
313}
314
315void World::setDefaultName(std::string name)
316{
317 OBSERVE;
318 defaultName = name;
319};
320
321class ThermoStatContainer * World::getThermostats()
322{
323 return Thermostats;
324}
325
326
327int World::getExitFlag() {
328 return ExitFlag;
329}
330
331void World::setExitFlag(int flag) {
332 if (ExitFlag < flag)
333 ExitFlag = flag;
334}
335
336/******************** Methods to change World state *********************/
337
338molecule* World::createMolecule(){
339 OBSERVE;
340 molecule *mol = NULL;
341 mol = NewMolecule();
342 moleculeId_t id = moleculeIdPool.getNextId();
343 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
344 mol->setId(id);
345 // store the molecule by ID
346 molecules[mol->getId()] = mol;
347 _lastchangedmol = mol;
348 _lastchangedmolid = mol->getId();
349 NOTIFY(MoleculeInserted);
350 return mol;
351}
352
353molecule* World::recreateMolecule(const moleculeId_t &_id)
354{
355 molecule *mol = NULL;
356 if (!molecules.count(_id)) {
357 OBSERVE;
358 mol = NewMolecule();
359 mol->setId(_id);
360 // store the molecule by ID
361 molecules[mol->getId()] = mol;
362 _lastchangedmol = mol;
363 _lastchangedmolid = mol->getId();
364 NOTIFY(MoleculeInserted);
365 }
366 return mol;
367}
368
369void World::destroyMolecule(molecule* mol){
370 ASSERT(mol,"Molecule that was meant to be destroyed did not exist");
371 destroyMolecule(mol->getId());
372}
373
374void World::destroyMolecule(moleculeId_t id){
375 molecule *mol = molecules[id];
376 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
377 // give notice about immediate removal
378 {
379 OBSERVE;
380 _lastchangedmol = mol;
381 _lastchangedmolid = mol->getId();
382 NOTIFY(MoleculeRemoved);
383 }
384 if (isMoleculeSelected(id)) {
385 selectedMolecules.erase(id);
386 NOTIFY(SelectionChanged);
387 }
388 DeleteMolecule(mol);
389 molecules.erase(id);
390 moleculeIdPool.releaseId(id);
391}
392
393atom *World::createAtom(const CreateAtomNotificationType _notify){
394 OBSERVE;
395 atomId_t id = atomIdPool.getNextId();
396 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
397 atom *res = NewAtom(id);
398 res->setWorld(this);
399 // store the atom by ID
400 atoms[res->getId()] = res;
401 _lastchangedatom = res;
402 _lastchangedatomid = res->getId();
403 if (_notify == NOTIFY_ON_CREATE_ATOM)
404 NOTIFY(AtomInserted);
405 return res;
406}
407
408atom *World::recreateAtom(const atomId_t _id){
409 if (!atoms.count(_id)) {
410 OBSERVE;
411 atom *res = NewAtom(_id);
412 res->setWorld(this);
413 // store the atom by ID
414 atoms[res->getId()] = res;
415 _lastchangedatom = res;
416 _lastchangedatomid = res->getId();
417 NOTIFY(AtomInserted);
418 return res;
419 } else
420 return NULL;
421}
422
423
424int World::registerAtom(atom *atom){
425 OBSERVE;
426 atomId_t id = atomIdPool.getNextId();
427 atom->setId(id);
428 atom->setWorld(this);
429 atoms[atom->getId()] = atom;
430 _lastchangedatom = atom;
431 _lastchangedatomid = atom->getId();
432 NOTIFY(AtomInserted);
433 return atom->getId();
434}
435
436void World::destroyAtom(atom* atom){
437 int id = atom->getId();
438 destroyAtom(id);
439}
440
441void World::destroyAtom(atomId_t id) {
442 atom *atom = atoms[id];
443 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
444 // give notice about immediate removal
445 {
446 OBSERVE;
447 _lastchangedatom = atom;
448 _lastchangedatomid = atom->getId();
449 NOTIFY(AtomRemoved);
450 }
451 // check if it's the last atom
452 molecule *_mol = const_cast<molecule *>(atom->getMolecule());
453 if ((_mol == NULL) || (_mol->getAtomCount() > 1))
454 _mol = NULL;
455 if (isAtomSelected(id)) {
456 selectedAtoms.erase(id);
457 NOTIFY(SelectionChanged);
458 }
459 DeleteAtom(atom);
460 atoms.erase(id);
461 atomIdPool.releaseId(id);
462 // remove molecule if empty
463 if (_mol != NULL)
464 destroyMolecule(_mol);
465}
466
467bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
468 OBSERVE;
469 // in case this call did not originate from inside the atom, we redirect it,
470 // to also let it know that it has changed
471 if(!target){
472 target = atoms[oldId];
473 ASSERT(target,"Atom with that ID not found");
474 return target->changeId(newId);
475 }
476 else{
477 if(atomIdPool.reserveId(newId)){
478 atoms.erase(oldId);
479 atoms.insert(pair<atomId_t,atom*>(newId,target));
480 return true;
481 }
482 else{
483 return false;
484 }
485 }
486}
487
488bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
489 OBSERVE;
490 // in case this call did not originate from inside the atom, we redirect it,
491 // to also let it know that it has changed
492 if(!target){
493 target = molecules[oldId];
494 ASSERT(target,"Molecule with that ID not found");
495 return target->changeId(newId);
496 }
497 else{
498 if(moleculeIdPool.reserveId(newId)){
499 molecules.erase(oldId);
500 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
501 return true;
502 }
503 else{
504 return false;
505 }
506 }
507}
508
509ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
510 ActionTrait manipulateTrait(name);
511 return new ManipulateAtomsProcess(op, descr,manipulateTrait);
512}
513
514ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
515 return manipulateAtoms(op,name,AllAtoms());
516}
517
518/********************* Internal Change methods for double Callback and Observer mechanism ********/
519
520void World::doManipulate(ManipulateAtomsProcess *proc){
521 proc->signOn(this);
522 {
523 OBSERVE;
524 proc->doManipulate(this);
525 }
526 proc->signOff(this);
527}
528/******************************* Iterators ********************************/
529
530// external parts with observers
531
532CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
533
534CONSTRUCT_SELECTIVE_CONST_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
535
536World::AtomIterator
537World::getAtomIter(AtomDescriptor descr){
538 return AtomIterator(descr,atoms);
539}
540
541World::AtomConstIterator
542World::getAtomIter(AtomDescriptor descr) const{
543 return AtomConstIterator(descr,atoms);
544}
545
546World::AtomIterator
547World::getAtomIter(){
548 return AtomIterator(AllAtoms(),atoms);
549}
550
551World::AtomConstIterator
552World::getAtomIter() const{
553 return AtomConstIterator(AllAtoms(),atoms);
554}
555
556World::AtomIterator
557World::atomEnd(){
558 return AtomIterator(AllAtoms(),atoms,atoms.end());
559}
560
561World::AtomConstIterator
562World::atomEnd() const{
563 return AtomConstIterator(AllAtoms(),atoms,atoms.end());
564}
565
566CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
567
568CONSTRUCT_SELECTIVE_CONST_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
569
570World::MoleculeIterator
571World::getMoleculeIter(MoleculeDescriptor descr){
572 return MoleculeIterator(descr,molecules);
573}
574
575World::MoleculeConstIterator
576World::getMoleculeIter(MoleculeDescriptor descr) const{
577 return MoleculeConstIterator(descr,molecules);
578}
579
580World::MoleculeIterator
581World::getMoleculeIter(){
582 return MoleculeIterator(AllMolecules(),molecules);
583}
584
585World::MoleculeConstIterator
586World::getMoleculeIter() const{
587 return MoleculeConstIterator(AllMolecules(),molecules);
588}
589
590World::MoleculeIterator
591World::moleculeEnd(){
592 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
593}
594
595World::MoleculeConstIterator
596World::moleculeEnd() const{
597 return MoleculeConstIterator(AllMolecules(),molecules,molecules.end());
598}
599
600// Internal parts, without observers
601
602// Build the AtomIterator from template
603CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
604
605
606World::internal_AtomIterator
607World::getAtomIter_internal(AtomDescriptor descr){
608 return internal_AtomIterator(descr,atoms.getContent());
609}
610
611World::internal_AtomIterator
612World::atomEnd_internal(){
613 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
614}
615
616// build the MoleculeIterator from template
617CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
618
619World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
620 return internal_MoleculeIterator(descr,molecules.getContent());
621}
622
623World::internal_MoleculeIterator World::moleculeEnd_internal(){
624 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
625}
626
627/************************** Selection of Atoms and molecules ******************/
628
629// translate type's selection member functions to overloaded with specific type
630
631template <class T>
632void World::selectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
633{
634 std::for_each(_begin,_end,
635 boost::bind(&World::selectInstance<typename T::value_type::second_type>,
636 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
637}
638
639template <class T>
640void World::unselectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
641{
642 std::for_each(_begin,_end,
643 boost::bind(&World::unselectInstance<typename T::value_type::second_type>,
644 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
645}
646
647// Atoms
648
649void World::clearAtomSelection(){
650 OBSERVE;
651 NOTIFY(SelectionChanged);
652 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
653 selectedAtoms.clear();
654}
655
656void World::invertAtomSelection(){
657 // get all atoms not selected
658 AtomComposite invertedSelection(getAllAtoms());
659 bool (World::*predicate)(const atom*) const = &World::isSelected; // needed for type resolution of overloaded function
660 AtomComposite::iterator iter =
661 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
662 std::bind1st(std::mem_fun(predicate), this));
663 invertedSelection.erase(iter, invertedSelection.end());
664 // apply new selection
665 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
666 selectedAtoms.clear();
667 void (World::*selector)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
668 std::for_each(invertedSelection.begin(),invertedSelection.end(),
669 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
670}
671
672void World::popAtomSelection(){
673 if (!selectedAtoms_Stack.empty()) {
674 OBSERVE;
675 NOTIFY(SelectionChanged);
676 const atomIdsVector_t atomids = selectedAtoms_Stack.top();
677 boost::function<void (const atomId_t)> IdSelector =
678 boost::bind(static_cast<void (World::*)(const atomId_t)>(&World::selectAtom), this, _1);
679 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
680 selectedAtoms.clear();
681 std::for_each(atomids.begin(),atomids.end(), IdSelector);
682 selectedAtoms_Stack.pop();
683 }
684}
685
686void World::pushAtomSelection(){
687 OBSERVE;
688 NOTIFY(SelectionChanged);
689 atomIdsVector_t atomids(countSelectedAtoms(), (atomId_t)-1);
690 std::copy(
691 MapKeyIterator<AtomSelectionConstIterator>(beginAtomSelection()),
692 MapKeyIterator<AtomSelectionConstIterator>(endAtomSelection()),
693 atomids.begin());
694 selectedAtoms_Stack.push( atomids );
695 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
696 selectedAtoms.clear();
697}
698
699void World::selectAtom(const atom *_atom){
700 OBSERVE;
701 NOTIFY(SelectionChanged);
702 // atom * is unchanged in this function, but we do store entity as changeable
703 ASSERT(_atom,"Invalid pointer in selection of atom");
704 selectAtom(_atom->getId());
705}
706
707void World::selectAtom(const atomId_t id){
708 OBSERVE;
709 NOTIFY(SelectionChanged);
710 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
711 selectedAtoms[id]=atoms[id];
712 atoms[id]->select();
713}
714
715void World::selectAllAtoms(AtomDescriptor descr){
716 OBSERVE;
717 NOTIFY(SelectionChanged);
718 internal_AtomIterator begin = getAtomIter_internal(descr);
719 internal_AtomIterator end = atomEnd_internal();
720 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
721 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
722}
723
724void World::selectAtomsOfMolecule(const molecule *_mol){
725 OBSERVE;
726 NOTIFY(SelectionChanged);
727 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
728 // need to make it const to get the fast iterators
729 const molecule *mol = _mol;
730 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
731 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
732}
733
734void World::selectAtomsOfMolecule(const moleculeId_t id){
735 OBSERVE;
736 NOTIFY(SelectionChanged);
737 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
738 selectAtomsOfMolecule(molecules[id]);
739}
740
741void World::unselectAtom(const atom *_atom){
742 OBSERVE;
743 NOTIFY(SelectionChanged);
744 ASSERT(_atom,"Invalid pointer in unselection of atom");
745 unselectAtom(_atom->getId());
746}
747
748void World::unselectAtom(const atomId_t id){
749 OBSERVE;
750 NOTIFY(SelectionChanged);
751 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
752 atoms[id]->unselect();
753 selectedAtoms.erase(id);
754}
755
756void World::unselectAllAtoms(AtomDescriptor descr){
757 OBSERVE;
758 NOTIFY(SelectionChanged);
759 internal_AtomIterator begin = getAtomIter_internal(descr);
760 internal_AtomIterator end = atomEnd_internal();
761 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
762 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
763}
764
765void World::unselectAtomsOfMolecule(const molecule *_mol){
766 OBSERVE;
767 NOTIFY(SelectionChanged);
768 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
769 // need to make it const to get the fast iterators
770 const molecule *mol = _mol;
771 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
772 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unselect... see above
773}
774
775void World::unselectAtomsOfMolecule(const moleculeId_t id){
776 OBSERVE;
777 NOTIFY(SelectionChanged);
778 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
779 unselectAtomsOfMolecule(molecules[id]);
780}
781
782size_t World::countSelectedAtoms() const {
783 size_t count = 0;
784 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
785 count++;
786 return count;
787}
788
789bool World::isSelected(const atom *_atom) const {
790 const bool status = isAtomSelected(_atom->getId());
791 ASSERT( status == _atom->selected,
792 "World::isSelected() - mismatch between selection state in atom "+
793 toString(_atom->getId())+" and World.");
794 return status;
795}
796
797bool World::isAtomSelected(const atomId_t no) const {
798 return selectedAtoms.find(no) != selectedAtoms.end();
799}
800
801std::vector<atom *> World::getSelectedAtoms() {
802 std::vector<atom *> returnAtoms;
803 std::transform(
804 selectedAtoms.begin(),
805 selectedAtoms.end(),
806 back_inserter(returnAtoms),
807 _take<atom*,World::AtomSet::value_type>::get);
808 return returnAtoms;
809}
810
811std::vector<const atom *> World::getSelectedAtoms() const {
812 std::vector<const atom *> returnAtoms;
813 std::transform(
814 selectedAtoms.begin(),
815 selectedAtoms.end(),
816 back_inserter(returnAtoms),
817 _take<atom*,World::AtomSet::value_type>::get);
818 return returnAtoms;
819}
820
821std::vector<atomId_t> World::getSelectedAtomIds() const {
822 std::vector<atomId_t> returnAtomIds;
823 std::transform(
824 selectedAtoms.begin(),
825 selectedAtoms.end(),
826 back_inserter(returnAtomIds),
827 _take<atom*,World::AtomSet::value_type>::getKey);
828 return returnAtomIds;
829}
830
831// Molecules
832
833void World::clearMoleculeSelection(){
834 OBSERVE;
835 NOTIFY(SelectionChanged);
836 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
837 selectedMolecules.clear();
838}
839
840void World::invertMoleculeSelection(){
841 // get all molecules not selected
842 typedef std::vector<molecule *> MoleculeVector_t;
843 MoleculeVector_t invertedSelection(getAllMolecules());
844 bool (World::*predicate)(const molecule*) const = &World::isSelected; // needed for type resolution of overloaded function
845 MoleculeVector_t::iterator iter =
846 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
847 std::bind1st(std::mem_fun(predicate), this));
848 invertedSelection.erase(iter, invertedSelection.end());
849 // apply new selection
850 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
851 selectedMolecules.clear();
852 void (World::*selector)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
853 std::for_each(invertedSelection.begin(),invertedSelection.end(),
854 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
855}
856
857void World::popMoleculeSelection(){
858 if (!selectedMolecules_Stack.empty()) {
859 OBSERVE;
860 NOTIFY(SelectionChanged);
861 const moleculeIdsVector_t moleculeids = selectedMolecules_Stack.top();
862 boost::function<void (const moleculeId_t)> IdSelector =
863 boost::bind(static_cast<void (World::*)(const moleculeId_t)>(&World::selectMolecule), this, _1);
864 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
865 selectedMolecules.clear();
866 std::for_each(moleculeids.begin(),moleculeids.end(), IdSelector);
867 selectedMolecules_Stack.pop();
868 }
869}
870
871void World::pushMoleculeSelection(){
872 OBSERVE;
873 NOTIFY(SelectionChanged);
874 moleculeIdsVector_t moleculeids(countSelectedMolecules(), (moleculeId_t)-1);
875 boost::function<moleculeId_t (const molecule*)> IdRetriever =
876 boost::bind(&molecule::getId, _1);
877 std::copy(
878 MapKeyIterator<MoleculeSelectionConstIterator>(beginMoleculeSelection()),
879 MapKeyIterator<MoleculeSelectionConstIterator>(endMoleculeSelection()),
880 moleculeids.begin());
881 selectedMolecules_Stack.push( moleculeids );
882 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
883 selectedMolecules.clear();
884}
885
886void World::selectMolecule(const molecule *_mol){
887 OBSERVE;
888 NOTIFY(SelectionChanged);
889 // molecule * is unchanged in this function, but we do store entity as changeable
890 ASSERT(_mol,"Invalid pointer to molecule in selection");
891 selectMolecule(_mol->getId());
892}
893
894void World::selectMolecule(const moleculeId_t id){
895 OBSERVE;
896 NOTIFY(SelectionChanged);
897 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
898 molecules[id]->select();
899 selectedMolecules[id]=molecules[id];
900}
901
902void World::selectAllMolecules(MoleculeDescriptor descr){
903 OBSERVE;
904 NOTIFY(SelectionChanged);
905 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
906 internal_MoleculeIterator end = moleculeEnd_internal();
907 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
908 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
909}
910
911void World::selectMoleculeOfAtom(const atom *_atom){
912 OBSERVE;
913 NOTIFY(SelectionChanged);
914 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
915 const molecule *mol=_atom->getMolecule();
916 // the atom might not be part of a molecule
917 if(mol){
918 selectMolecule(mol);
919 }
920}
921
922void World::selectMoleculeOfAtom(const atomId_t id){
923 OBSERVE;
924 NOTIFY(SelectionChanged);
925 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
926 selectMoleculeOfAtom(atoms[id]);
927}
928
929void World::unselectMolecule(const molecule *_mol){
930 OBSERVE;
931 NOTIFY(SelectionChanged);
932 ASSERT(_mol,"invalid pointer in unselection of molecule");
933 unselectMolecule(_mol->getId());
934}
935
936void World::unselectMolecule(const moleculeId_t id){
937 OBSERVE;
938 NOTIFY(SelectionChanged);
939 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
940 molecules[id]->unselect();
941 selectedMolecules.erase(id);
942}
943
944void World::unselectAllMolecules(MoleculeDescriptor descr){
945 OBSERVE;
946 NOTIFY(SelectionChanged);
947 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
948 internal_MoleculeIterator end = moleculeEnd_internal();
949 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
950 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
951}
952
953void World::unselectMoleculeOfAtom(const atom *_atom){
954 OBSERVE;
955 NOTIFY(SelectionChanged);
956 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
957 const molecule *mol=_atom->getMolecule();
958 // the atom might not be part of a molecule
959 if(mol){
960 unselectMolecule(mol);
961 }
962}
963
964void World::unselectMoleculeOfAtom(const atomId_t id){
965 OBSERVE;
966 NOTIFY(SelectionChanged);
967 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
968 unselectMoleculeOfAtom(atoms[id]);
969}
970
971size_t World::countSelectedMolecules() const {
972 size_t count = 0;
973 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
974 count++;
975 return count;
976}
977
978bool World::isSelected(const molecule *_mol) const {
979 const bool status = isMoleculeSelected(_mol->getId());
980 ASSERT( status == _mol->selected,
981 "World::isSelected() - mismatch in selection status between mol "+
982 toString(_mol->getId())+" and World.");
983 return status;
984}
985
986bool World::isMoleculeSelected(const moleculeId_t no) const {
987 return selectedMolecules.find(no) != selectedMolecules.end();
988}
989
990std::vector<molecule *> World::getSelectedMolecules() {
991 std::vector<molecule *> returnMolecules;
992 std::transform(
993 selectedMolecules.begin(),
994 selectedMolecules.end(),
995 back_inserter(returnMolecules),
996 _take<molecule*,World::MoleculeSet::value_type>::get);
997 return returnMolecules;
998}
999
1000std::vector<const molecule *> World::getSelectedMolecules() const {
1001 std::vector<const molecule *> returnMolecules;
1002 std::transform(
1003 selectedMolecules.begin(),
1004 selectedMolecules.end(),
1005 back_inserter(returnMolecules),
1006 _take<molecule*,World::MoleculeSet::value_type>::get);
1007 return returnMolecules;
1008}
1009
1010std::vector<moleculeId_t> World::getSelectedMoleculeIds() const {
1011 std::vector<moleculeId_t> returnMoleculeIds;
1012 std::transform(
1013 selectedMolecules.begin(),
1014 selectedMolecules.end(),
1015 back_inserter(returnMoleculeIds),
1016 _take<molecule*,World::MoleculeSet::value_type>::getKey);
1017 return returnMoleculeIds;
1018}
1019
1020/******************* Iterators over Selection *****************************/
1021World::AtomSelectionIterator World::beginAtomSelection(){
1022 return selectedAtoms.begin();
1023}
1024
1025World::AtomSelectionIterator World::endAtomSelection(){
1026 return selectedAtoms.end();
1027}
1028
1029World::AtomSelectionConstIterator World::beginAtomSelection() const{
1030 return selectedAtoms.begin();
1031}
1032
1033World::AtomSelectionConstIterator World::endAtomSelection() const{
1034 return selectedAtoms.end();
1035}
1036
1037
1038World::MoleculeSelectionIterator World::beginMoleculeSelection(){
1039 return selectedMolecules.begin();
1040}
1041
1042World::MoleculeSelectionIterator World::endMoleculeSelection(){
1043 return selectedMolecules.end();
1044}
1045
1046World::MoleculeSelectionConstIterator World::beginMoleculeSelection() const{
1047 return selectedMolecules.begin();
1048}
1049
1050World::MoleculeSelectionConstIterator World::endMoleculeSelection() const{
1051 return selectedMolecules.end();
1052}
1053
1054/******************************* Singleton Stuff **************************/
1055
1056World::World() :
1057 Observable("World"),
1058 BG(new BondGraph(true)), // assume Angstroem for the moment
1059 periode(new periodentafel(true)),
1060 configuration(new config),
1061 homologies(new HomologyContainer()),
1062 Thermostats(new ThermoStatContainer),
1063 ExitFlag(0),
1064 atoms(this),
1065 selectedAtoms(this),
1066 atomIdPool(0, 0, 0),
1067 molecules(this),
1068 selectedMolecules(this),
1069 moleculeIdPool(0, 20,100)
1070{
1071 cell_size = new Box;
1072 RealSpaceMatrix domain;
1073 domain.at(0,0) = 20;
1074 domain.at(1,1) = 20;
1075 domain.at(2,2) = 20;
1076 cell_size->setM(domain);
1077 LCcontroller = new LinkedCell::LinkedCell_Controller(*cell_size);
1078 defaultName = "none";
1079 Channels *OurChannel = new Channels;
1080 Observable::insertNotificationChannel( std::make_pair( static_cast<Observable *>(this), OurChannel) );
1081 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
1082 OurChannel->addChannel(type);
1083}
1084
1085World::~World()
1086{
1087 delete LCcontroller;
1088 delete cell_size;
1089 MoleculeSet::iterator molIter;
1090 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
1091 DeleteMolecule((*molIter).second);
1092 }
1093 molecules.clear();
1094 AtomSet::iterator atIter;
1095 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
1096 DeleteAtom((*atIter).second);
1097 }
1098 atoms.clear();
1099
1100 delete BG;
1101 delete periode;
1102 delete configuration;
1103 delete Thermostats;
1104 delete homologies;
1105}
1106
1107// Explicit instantiation of the singleton mechanism at this point
1108
1109// moleculeId_t und atomId_t sind gleicher Basistyp, deswegen nur einen von beiden konstruieren
1110CONSTRUCT_IDPOOL(atomId_t, uniqueId)
1111CONSTRUCT_IDPOOL(moleculeId_t, continuousId)
1112
1113CONSTRUCT_SINGLETON(World)
1114
1115CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet, UnobservedIterator<World::AtomSTLSet> )
1116
1117CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet, UnobservedIterator<World::MoleculeSTLSet> )
Note: See TracBrowser for help on using the repository browser.