source: src/World.cpp@ 7672284

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 7672284 was 0249ce, checked in by Frederik Heber <heber@…>, 8 years ago

FIX: Pop..Action need to check whether stack is actually non-empty.

  • this caused a segfault in python all-actions regression test.
  • Property mode set to 100644
File size: 32.2 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
223bool 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
236void copyBondgraph(const unsigned int _srcstep, const unsigned int _deststep)
237{
238 // gather all bonds from _srcstep
239 std::set<bond *> SetOfBonds;
240 for (World::AtomConstIterator iter = const_cast<const World &>(World::getInstance()).getAtomIter();
241 iter != const_cast<const World &>(World::getInstance()).atomEnd(); ++iter) {
242 const atom * const Walker = *iter;
243 const BondList bonds = Walker->getListOfBondsAtStep(_srcstep);
244 BOOST_FOREACH( bond::ptr bondptr, bonds) {
245 SetOfBonds.insert(bondptr.get());
246 }
247 }
248 LOG(4, "DEBUG: We gathered " << SetOfBonds.size() << " bonds in total.");
249
250 // copy bond to new time step
251 for (std::set<bond *>::const_iterator bonditer = SetOfBonds.begin();
252 bonditer != SetOfBonds.end(); ++bonditer) {
253 const atom * const Walker = (*bonditer)->leftatom;
254 const atom * const OtherWalker = (*bonditer)->rightatom;
255 bond::ptr const _bond =
256 const_cast<atom *>(Walker)->addBond(_deststep, const_cast<atom *>(OtherWalker));
257 _bond->setDegree((*bonditer)->getDegree());
258 }
259}
260
261void World::setTime(const unsigned int _step)
262{
263 if (_step != WorldTime::getTime()) {
264 const unsigned int oldstep = WorldTime::getTime();
265
266 // 1. copy bond graph (such not each addBond causes GUI update)
267 if (!areBondsPresent(_step)) {
268// AtomComposite Set = getAllAtoms();
269// BG->cleanAdjacencyList(Set);
270 copyBondgraph(oldstep, _step);
271 }
272
273 // 2. set new time
274 WorldTime::getInstance().setTime(_step);
275
276 // 4. scan for connected subgraphs => molecules
277 DepthFirstSearchAnalysis DFS;
278 DFS();
279 DFS.UpdateMoleculeStructure();
280 }
281}
282
283std::string World::getDefaultName() {
284 return defaultName;
285}
286
287void World::setDefaultName(std::string name)
288{
289 OBSERVE;
290 defaultName = name;
291};
292
293class ThermoStatContainer * World::getThermostats()
294{
295 return Thermostats;
296}
297
298
299int World::getExitFlag() {
300 return ExitFlag;
301}
302
303void World::setExitFlag(int flag) {
304 if (ExitFlag < flag)
305 ExitFlag = flag;
306}
307
308/******************** Methods to change World state *********************/
309
310molecule* World::createMolecule(){
311 OBSERVE;
312 molecule *mol = NULL;
313 mol = NewMolecule();
314 moleculeId_t id = moleculeIdPool.getNextId();
315 ASSERT(!molecules.count(id),"proposed id did not specify an unused ID");
316 mol->setId(id);
317 // store the molecule by ID
318 molecules[mol->getId()] = mol;
319 _lastchangedmol = mol;
320 _lastchangedmolid = mol->getId();
321 NOTIFY(MoleculeInserted);
322 return mol;
323}
324
325molecule* World::recreateMolecule(const moleculeId_t &_id)
326{
327 molecule *mol = NULL;
328 if (!molecules.count(_id)) {
329 OBSERVE;
330 mol = NewMolecule();
331 mol->setId(_id);
332 // store the molecule by ID
333 molecules[mol->getId()] = mol;
334 _lastchangedmol = mol;
335 _lastchangedmolid = mol->getId();
336 NOTIFY(MoleculeInserted);
337 }
338 return mol;
339}
340
341void World::destroyMolecule(molecule* mol){
342 ASSERT(mol,"Molecule that was meant to be destroyed did not exist");
343 destroyMolecule(mol->getId());
344}
345
346void World::destroyMolecule(moleculeId_t id){
347 molecule *mol = molecules[id];
348 ASSERT(mol,"Molecule id that was meant to be destroyed did not exist");
349 // give notice about immediate removal
350 {
351 OBSERVE;
352 _lastchangedmol = mol;
353 _lastchangedmolid = mol->getId();
354 NOTIFY(MoleculeRemoved);
355 }
356 if (isMoleculeSelected(id)) {
357 selectedMolecules.erase(id);
358 NOTIFY(SelectionChanged);
359 }
360 DeleteMolecule(mol);
361 molecules.erase(id);
362 moleculeIdPool.releaseId(id);
363}
364
365atom *World::createAtom(){
366 OBSERVE;
367 atomId_t id = atomIdPool.getNextId();
368 ASSERT(!atoms.count(id),"proposed id did not specify an unused ID");
369 atom *res = NewAtom(id);
370 res->setWorld(this);
371 // store the atom by ID
372 atoms[res->getId()] = res;
373 _lastchangedatom = res;
374 _lastchangedatomid = res->getId();
375 NOTIFY(AtomInserted);
376 return res;
377}
378
379atom *World::recreateAtom(const atomId_t _id){
380 if (!atoms.count(_id)) {
381 OBSERVE;
382 atom *res = NewAtom(_id);
383 res->setWorld(this);
384 // store the atom by ID
385 atoms[res->getId()] = res;
386 _lastchangedatom = res;
387 _lastchangedatomid = res->getId();
388 NOTIFY(AtomInserted);
389 return res;
390 } else
391 return NULL;
392}
393
394
395int World::registerAtom(atom *atom){
396 OBSERVE;
397 atomId_t id = atomIdPool.getNextId();
398 atom->setId(id);
399 atom->setWorld(this);
400 atoms[atom->getId()] = atom;
401 _lastchangedatom = atom;
402 _lastchangedatomid = atom->getId();
403 NOTIFY(AtomInserted);
404 return atom->getId();
405}
406
407void World::destroyAtom(atom* atom){
408 int id = atom->getId();
409 destroyAtom(id);
410}
411
412void World::destroyAtom(atomId_t id) {
413 atom *atom = atoms[id];
414 ASSERT(atom,"Atom ID that was meant to be destroyed did not exist");
415 // give notice about immediate removal
416 {
417 OBSERVE;
418 _lastchangedatom = atom;
419 _lastchangedatomid = atom->getId();
420 NOTIFY(AtomRemoved);
421 }
422 // check if it's the last atom
423 molecule *_mol = const_cast<molecule *>(atom->getMolecule());
424 if ((_mol == NULL) || (_mol->getAtomCount() > 1))
425 _mol = NULL;
426 if (isAtomSelected(id)) {
427 selectedAtoms.erase(id);
428 NOTIFY(SelectionChanged);
429 }
430 DeleteAtom(atom);
431 atoms.erase(id);
432 atomIdPool.releaseId(id);
433 // remove molecule if empty
434 if (_mol != NULL)
435 destroyMolecule(_mol);
436}
437
438bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){
439 OBSERVE;
440 // in case this call did not originate from inside the atom, we redirect it,
441 // to also let it know that it has changed
442 if(!target){
443 target = atoms[oldId];
444 ASSERT(target,"Atom with that ID not found");
445 return target->changeId(newId);
446 }
447 else{
448 if(atomIdPool.reserveId(newId)){
449 atoms.erase(oldId);
450 atoms.insert(pair<atomId_t,atom*>(newId,target));
451 return true;
452 }
453 else{
454 return false;
455 }
456 }
457}
458
459bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){
460 OBSERVE;
461 // in case this call did not originate from inside the atom, we redirect it,
462 // to also let it know that it has changed
463 if(!target){
464 target = molecules[oldId];
465 ASSERT(target,"Molecule with that ID not found");
466 return target->changeId(newId);
467 }
468 else{
469 if(moleculeIdPool.reserveId(newId)){
470 molecules.erase(oldId);
471 molecules.insert(pair<moleculeId_t,molecule*>(newId,target));
472 return true;
473 }
474 else{
475 return false;
476 }
477 }
478}
479
480ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name,AtomDescriptor descr){
481 ActionTrait manipulateTrait(name);
482 return new ManipulateAtomsProcess(op, descr,manipulateTrait);
483}
484
485ManipulateAtomsProcess* World::manipulateAtoms(boost::function<void(atom*)> op,std::string name){
486 return manipulateAtoms(op,name,AllAtoms());
487}
488
489/********************* Internal Change methods for double Callback and Observer mechanism ********/
490
491void World::doManipulate(ManipulateAtomsProcess *proc){
492 proc->signOn(this);
493 {
494 OBSERVE;
495 proc->doManipulate(this);
496 }
497 proc->signOff(this);
498}
499/******************************* Iterators ********************************/
500
501// external parts with observers
502
503CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
504
505CONSTRUCT_SELECTIVE_CONST_ITERATOR(atom*,World::AtomSet,AtomDescriptor)
506
507World::AtomIterator
508World::getAtomIter(AtomDescriptor descr){
509 return AtomIterator(descr,atoms);
510}
511
512World::AtomConstIterator
513World::getAtomIter(AtomDescriptor descr) const{
514 return AtomConstIterator(descr,atoms);
515}
516
517World::AtomIterator
518World::getAtomIter(){
519 return AtomIterator(AllAtoms(),atoms);
520}
521
522World::AtomConstIterator
523World::getAtomIter() const{
524 return AtomConstIterator(AllAtoms(),atoms);
525}
526
527World::AtomIterator
528World::atomEnd(){
529 return AtomIterator(AllAtoms(),atoms,atoms.end());
530}
531
532World::AtomConstIterator
533World::atomEnd() const{
534 return AtomConstIterator(AllAtoms(),atoms,atoms.end());
535}
536
537CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
538
539CONSTRUCT_SELECTIVE_CONST_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor)
540
541World::MoleculeIterator
542World::getMoleculeIter(MoleculeDescriptor descr){
543 return MoleculeIterator(descr,molecules);
544}
545
546World::MoleculeConstIterator
547World::getMoleculeIter(MoleculeDescriptor descr) const{
548 return MoleculeConstIterator(descr,molecules);
549}
550
551World::MoleculeIterator
552World::getMoleculeIter(){
553 return MoleculeIterator(AllMolecules(),molecules);
554}
555
556World::MoleculeConstIterator
557World::getMoleculeIter() const{
558 return MoleculeConstIterator(AllMolecules(),molecules);
559}
560
561World::MoleculeIterator
562World::moleculeEnd(){
563 return MoleculeIterator(AllMolecules(),molecules,molecules.end());
564}
565
566World::MoleculeConstIterator
567World::moleculeEnd() const{
568 return MoleculeConstIterator(AllMolecules(),molecules,molecules.end());
569}
570
571// Internal parts, without observers
572
573// Build the AtomIterator from template
574CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor);
575
576
577World::internal_AtomIterator
578World::getAtomIter_internal(AtomDescriptor descr){
579 return internal_AtomIterator(descr,atoms.getContent());
580}
581
582World::internal_AtomIterator
583World::atomEnd_internal(){
584 return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal());
585}
586
587// build the MoleculeIterator from template
588CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor);
589
590World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){
591 return internal_MoleculeIterator(descr,molecules.getContent());
592}
593
594World::internal_MoleculeIterator World::moleculeEnd_internal(){
595 return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal());
596}
597
598/************************** Selection of Atoms and molecules ******************/
599
600// translate type's selection member functions to overloaded with specific type
601
602template <class T>
603void World::selectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
604{
605 std::for_each(_begin,_end,
606 boost::bind(&World::selectInstance<typename T::value_type::second_type>,
607 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
608}
609
610template <class T>
611void World::unselectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end)
612{
613 std::for_each(_begin,_end,
614 boost::bind(&World::unselectInstance<typename T::value_type::second_type>,
615 boost::bind(_take<typename T::value_type::second_type,typename T::value_type>::get, _1)));
616}
617
618// Atoms
619
620void World::clearAtomSelection(){
621 OBSERVE;
622 NOTIFY(SelectionChanged);
623 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
624 selectedAtoms.clear();
625}
626
627void World::invertAtomSelection(){
628 // get all atoms not selected
629 AtomComposite invertedSelection(getAllAtoms());
630 bool (World::*predicate)(const atom*) const = &World::isSelected; // needed for type resolution of overloaded function
631 AtomComposite::iterator iter =
632 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
633 std::bind1st(std::mem_fun(predicate), this));
634 invertedSelection.erase(iter, invertedSelection.end());
635 // apply new selection
636 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
637 selectedAtoms.clear();
638 void (World::*selector)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
639 std::for_each(invertedSelection.begin(),invertedSelection.end(),
640 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
641}
642
643void World::popAtomSelection(){
644 if (!selectedAtoms_Stack.empty()) {
645 OBSERVE;
646 NOTIFY(SelectionChanged);
647 const atomIdsVector_t atomids = selectedAtoms_Stack.top();
648 boost::function<void (const atomId_t)> IdSelector =
649 boost::bind(static_cast<void (World::*)(const atomId_t)>(&World::selectAtom), this, _1);
650 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
651 selectedAtoms.clear();
652 std::for_each(atomids.begin(),atomids.end(), IdSelector);
653 selectedAtoms_Stack.pop();
654 }
655}
656
657void World::pushAtomSelection(){
658 OBSERVE;
659 NOTIFY(SelectionChanged);
660 atomIdsVector_t atomids(countSelectedAtoms(), (atomId_t)-1);
661 std::copy(
662 MapKeyIterator<AtomSelectionConstIterator>(beginAtomSelection()),
663 MapKeyIterator<AtomSelectionConstIterator>(endAtomSelection()),
664 atomids.begin());
665 selectedAtoms_Stack.push( atomids );
666 unselectVectorOfInstances<AtomSet>(selectedAtoms.begin(), selectedAtoms.end());
667 selectedAtoms.clear();
668}
669
670void World::selectAtom(const atom *_atom){
671 OBSERVE;
672 NOTIFY(SelectionChanged);
673 // atom * is unchanged in this function, but we do store entity as changeable
674 ASSERT(_atom,"Invalid pointer in selection of atom");
675 selectAtom(_atom->getId());
676}
677
678void World::selectAtom(const atomId_t id){
679 OBSERVE;
680 NOTIFY(SelectionChanged);
681 ASSERT(atoms.count(id),"Atom Id selected that was not in the world");
682 selectedAtoms[id]=atoms[id];
683 atoms[id]->select();
684}
685
686void World::selectAllAtoms(AtomDescriptor descr){
687 OBSERVE;
688 NOTIFY(SelectionChanged);
689 internal_AtomIterator begin = getAtomIter_internal(descr);
690 internal_AtomIterator end = atomEnd_internal();
691 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
692 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
693}
694
695void World::selectAtomsOfMolecule(const molecule *_mol){
696 OBSERVE;
697 NOTIFY(SelectionChanged);
698 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
699 // need to make it const to get the fast iterators
700 const molecule *mol = _mol;
701 void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function
702 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above
703}
704
705void World::selectAtomsOfMolecule(const moleculeId_t id){
706 OBSERVE;
707 NOTIFY(SelectionChanged);
708 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
709 selectAtomsOfMolecule(molecules[id]);
710}
711
712void World::unselectAtom(const atom *_atom){
713 OBSERVE;
714 NOTIFY(SelectionChanged);
715 ASSERT(_atom,"Invalid pointer in unselection of atom");
716 unselectAtom(_atom->getId());
717}
718
719void World::unselectAtom(const atomId_t id){
720 OBSERVE;
721 NOTIFY(SelectionChanged);
722 ASSERT(atoms.count(id),"Atom Id unselected that was not in the world");
723 atoms[id]->unselect();
724 selectedAtoms.erase(id);
725}
726
727void World::unselectAllAtoms(AtomDescriptor descr){
728 OBSERVE;
729 NOTIFY(SelectionChanged);
730 internal_AtomIterator begin = getAtomIter_internal(descr);
731 internal_AtomIterator end = atomEnd_internal();
732 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
733 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
734}
735
736void World::unselectAtomsOfMolecule(const molecule *_mol){
737 OBSERVE;
738 NOTIFY(SelectionChanged);
739 ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule");
740 // need to make it const to get the fast iterators
741 const molecule *mol = _mol;
742 void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function
743 for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unselect... see above
744}
745
746void World::unselectAtomsOfMolecule(const moleculeId_t id){
747 OBSERVE;
748 NOTIFY(SelectionChanged);
749 ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule");
750 unselectAtomsOfMolecule(molecules[id]);
751}
752
753size_t World::countSelectedAtoms() const {
754 size_t count = 0;
755 for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter)
756 count++;
757 return count;
758}
759
760bool World::isSelected(const atom *_atom) const {
761 const bool status = isAtomSelected(_atom->getId());
762 ASSERT( status == _atom->selected,
763 "World::isSelected() - mismatch between selection state in atom "+
764 toString(_atom->getId())+" and World.");
765 return status;
766}
767
768bool World::isAtomSelected(const atomId_t no) const {
769 return selectedAtoms.find(no) != selectedAtoms.end();
770}
771
772std::vector<atom *> World::getSelectedAtoms() {
773 std::vector<atom *> returnAtoms;
774 std::transform(
775 selectedAtoms.begin(),
776 selectedAtoms.end(),
777 back_inserter(returnAtoms),
778 _take<atom*,World::AtomSet::value_type>::get);
779 return returnAtoms;
780}
781
782std::vector<const atom *> World::getSelectedAtoms() const {
783 std::vector<const atom *> returnAtoms;
784 std::transform(
785 selectedAtoms.begin(),
786 selectedAtoms.end(),
787 back_inserter(returnAtoms),
788 _take<atom*,World::AtomSet::value_type>::get);
789 return returnAtoms;
790}
791
792std::vector<atomId_t> World::getSelectedAtomIds() const {
793 std::vector<atomId_t> returnAtomIds;
794 std::transform(
795 selectedAtoms.begin(),
796 selectedAtoms.end(),
797 back_inserter(returnAtomIds),
798 _take<atom*,World::AtomSet::value_type>::getKey);
799 return returnAtomIds;
800}
801
802// Molecules
803
804void World::clearMoleculeSelection(){
805 OBSERVE;
806 NOTIFY(SelectionChanged);
807 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
808 selectedMolecules.clear();
809}
810
811void World::invertMoleculeSelection(){
812 // get all molecules not selected
813 typedef std::vector<molecule *> MoleculeVector_t;
814 MoleculeVector_t invertedSelection(getAllMolecules());
815 bool (World::*predicate)(const molecule*) const = &World::isSelected; // needed for type resolution of overloaded function
816 MoleculeVector_t::iterator iter =
817 std::remove_if(invertedSelection.begin(), invertedSelection.end(),
818 std::bind1st(std::mem_fun(predicate), this));
819 invertedSelection.erase(iter, invertedSelection.end());
820 // apply new selection
821 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
822 selectedMolecules.clear();
823 void (World::*selector)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
824 std::for_each(invertedSelection.begin(),invertedSelection.end(),
825 std::bind1st(std::mem_fun(selector),this)); // func is select... see above
826}
827
828void World::popMoleculeSelection(){
829 if (!selectedMolecules_Stack.empty()) {
830 OBSERVE;
831 NOTIFY(SelectionChanged);
832 const moleculeIdsVector_t moleculeids = selectedMolecules_Stack.top();
833 boost::function<void (const moleculeId_t)> IdSelector =
834 boost::bind(static_cast<void (World::*)(const moleculeId_t)>(&World::selectMolecule), this, _1);
835 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
836 selectedMolecules.clear();
837 std::for_each(moleculeids.begin(),moleculeids.end(), IdSelector);
838 selectedMolecules_Stack.pop();
839 }
840}
841
842void World::pushMoleculeSelection(){
843 OBSERVE;
844 NOTIFY(SelectionChanged);
845 moleculeIdsVector_t moleculeids(countSelectedMolecules(), (moleculeId_t)-1);
846 boost::function<moleculeId_t (const molecule*)> IdRetriever =
847 boost::bind(&molecule::getId, _1);
848 std::copy(
849 MapKeyIterator<MoleculeSelectionConstIterator>(beginMoleculeSelection()),
850 MapKeyIterator<MoleculeSelectionConstIterator>(endMoleculeSelection()),
851 moleculeids.begin());
852 selectedMolecules_Stack.push( moleculeids );
853 unselectVectorOfInstances<MoleculeSet>(selectedMolecules.begin(), selectedMolecules.end());
854 selectedMolecules.clear();
855}
856
857void World::selectMolecule(const molecule *_mol){
858 OBSERVE;
859 NOTIFY(SelectionChanged);
860 // molecule * is unchanged in this function, but we do store entity as changeable
861 ASSERT(_mol,"Invalid pointer to molecule in selection");
862 selectMolecule(_mol->getId());
863}
864
865void World::selectMolecule(const moleculeId_t id){
866 OBSERVE;
867 NOTIFY(SelectionChanged);
868 ASSERT(molecules.count(id),"Molecule Id selected that was not in the world");
869 molecules[id]->select();
870 selectedMolecules[id]=molecules[id];
871}
872
873void World::selectAllMolecules(MoleculeDescriptor descr){
874 OBSERVE;
875 NOTIFY(SelectionChanged);
876 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
877 internal_MoleculeIterator end = moleculeEnd_internal();
878 void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function
879 for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above
880}
881
882void World::selectMoleculeOfAtom(const atom *_atom){
883 OBSERVE;
884 NOTIFY(SelectionChanged);
885 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
886 const molecule *mol=_atom->getMolecule();
887 // the atom might not be part of a molecule
888 if(mol){
889 selectMolecule(mol);
890 }
891}
892
893void World::selectMoleculeOfAtom(const atomId_t id){
894 OBSERVE;
895 NOTIFY(SelectionChanged);
896 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
897 selectMoleculeOfAtom(atoms[id]);
898}
899
900void World::unselectMolecule(const molecule *_mol){
901 OBSERVE;
902 NOTIFY(SelectionChanged);
903 ASSERT(_mol,"invalid pointer in unselection of molecule");
904 unselectMolecule(_mol->getId());
905}
906
907void World::unselectMolecule(const moleculeId_t id){
908 OBSERVE;
909 NOTIFY(SelectionChanged);
910 ASSERT(molecules.count(id),"No such molecule with ID in unselection");
911 molecules[id]->unselect();
912 selectedMolecules.erase(id);
913}
914
915void World::unselectAllMolecules(MoleculeDescriptor descr){
916 OBSERVE;
917 NOTIFY(SelectionChanged);
918 internal_MoleculeIterator begin = getMoleculeIter_internal(descr);
919 internal_MoleculeIterator end = moleculeEnd_internal();
920 void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function
921 for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above
922}
923
924void World::unselectMoleculeOfAtom(const atom *_atom){
925 OBSERVE;
926 NOTIFY(SelectionChanged);
927 ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom");
928 const molecule *mol=_atom->getMolecule();
929 // the atom might not be part of a molecule
930 if(mol){
931 unselectMolecule(mol);
932 }
933}
934
935void World::unselectMoleculeOfAtom(const atomId_t id){
936 OBSERVE;
937 NOTIFY(SelectionChanged);
938 ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\
939 unselectMoleculeOfAtom(atoms[id]);
940}
941
942size_t World::countSelectedMolecules() const {
943 size_t count = 0;
944 for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter)
945 count++;
946 return count;
947}
948
949bool World::isSelected(const molecule *_mol) const {
950 const bool status = isMoleculeSelected(_mol->getId());
951 ASSERT( status == _mol->selected,
952 "World::isSelected() - mismatch in selection status between mol "+
953 toString(_mol->getId())+" and World.");
954 return status;
955}
956
957bool World::isMoleculeSelected(const moleculeId_t no) const {
958 return selectedMolecules.find(no) != selectedMolecules.end();
959}
960
961std::vector<molecule *> World::getSelectedMolecules() {
962 std::vector<molecule *> returnMolecules;
963 std::transform(
964 selectedMolecules.begin(),
965 selectedMolecules.end(),
966 back_inserter(returnMolecules),
967 _take<molecule*,World::MoleculeSet::value_type>::get);
968 return returnMolecules;
969}
970
971std::vector<const molecule *> World::getSelectedMolecules() const {
972 std::vector<const molecule *> returnMolecules;
973 std::transform(
974 selectedMolecules.begin(),
975 selectedMolecules.end(),
976 back_inserter(returnMolecules),
977 _take<molecule*,World::MoleculeSet::value_type>::get);
978 return returnMolecules;
979}
980
981std::vector<moleculeId_t> World::getSelectedMoleculeIds() const {
982 std::vector<moleculeId_t> returnMoleculeIds;
983 std::transform(
984 selectedMolecules.begin(),
985 selectedMolecules.end(),
986 back_inserter(returnMoleculeIds),
987 _take<molecule*,World::MoleculeSet::value_type>::getKey);
988 return returnMoleculeIds;
989}
990
991/******************* Iterators over Selection *****************************/
992World::AtomSelectionIterator World::beginAtomSelection(){
993 return selectedAtoms.begin();
994}
995
996World::AtomSelectionIterator World::endAtomSelection(){
997 return selectedAtoms.end();
998}
999
1000World::AtomSelectionConstIterator World::beginAtomSelection() const{
1001 return selectedAtoms.begin();
1002}
1003
1004World::AtomSelectionConstIterator World::endAtomSelection() const{
1005 return selectedAtoms.end();
1006}
1007
1008
1009World::MoleculeSelectionIterator World::beginMoleculeSelection(){
1010 return selectedMolecules.begin();
1011}
1012
1013World::MoleculeSelectionIterator World::endMoleculeSelection(){
1014 return selectedMolecules.end();
1015}
1016
1017World::MoleculeSelectionConstIterator World::beginMoleculeSelection() const{
1018 return selectedMolecules.begin();
1019}
1020
1021World::MoleculeSelectionConstIterator World::endMoleculeSelection() const{
1022 return selectedMolecules.end();
1023}
1024
1025/******************************* Singleton Stuff **************************/
1026
1027World::World() :
1028 Observable("World"),
1029 BG(new BondGraph(true)), // assume Angstroem for the moment
1030 periode(new periodentafel(true)),
1031 configuration(new config),
1032 homologies(new HomologyContainer()),
1033 Thermostats(new ThermoStatContainer),
1034 ExitFlag(0),
1035 atoms(this),
1036 selectedAtoms(this),
1037 atomIdPool(0, 20, 100),
1038 molecules(this),
1039 selectedMolecules(this),
1040 moleculeIdPool(0, 20,100)
1041{
1042 cell_size = new Box;
1043 RealSpaceMatrix domain;
1044 domain.at(0,0) = 20;
1045 domain.at(1,1) = 20;
1046 domain.at(2,2) = 20;
1047 cell_size->setM(domain);
1048 LCcontroller = new LinkedCell::LinkedCell_Controller(*cell_size);
1049 defaultName = "none";
1050 Channels *OurChannel = new Channels;
1051 Observable::insertNotificationChannel( std::make_pair( static_cast<Observable *>(this), OurChannel) );
1052 for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type)
1053 OurChannel->addChannel(type);
1054}
1055
1056World::~World()
1057{
1058 delete LCcontroller;
1059 delete cell_size;
1060 MoleculeSet::iterator molIter;
1061 for(molIter=molecules.begin();molIter!=molecules.end();++molIter){
1062 DeleteMolecule((*molIter).second);
1063 }
1064 molecules.clear();
1065 AtomSet::iterator atIter;
1066 for(atIter=atoms.begin();atIter!=atoms.end();++atIter){
1067 DeleteAtom((*atIter).second);
1068 }
1069 atoms.clear();
1070
1071 delete BG;
1072 delete periode;
1073 delete configuration;
1074 delete Thermostats;
1075 delete homologies;
1076}
1077
1078// Explicit instantiation of the singleton mechanism at this point
1079
1080// moleculeId_t und atomId_t sind gleicher Basistyp, deswegen nur einen von beiden konstruieren
1081CONSTRUCT_IDPOOL(atomId_t, uniqueId)
1082CONSTRUCT_IDPOOL(moleculeId_t, continuousId)
1083
1084CONSTRUCT_SINGLETON(World)
1085
1086CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet, UnobservedIterator<World::AtomSTLSet> )
1087
1088CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet, UnobservedIterator<World::MoleculeSTLSet> )
Note: See TracBrowser for help on using the repository browser.