/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * World.cpp * * Created on: Feb 3, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "World.hpp" #include #include "Actions/ActionTrait.hpp" #include "Actions/ManipulateAtomsProcess.hpp" #include "Atom/atom.hpp" #include "Box.hpp" #include "CodePatterns/Assert.hpp" #include "config.hpp" #include "Descriptors/AtomDescriptor.hpp" #include "Descriptors/AtomDescriptor_impl.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "Descriptors/AtomSelectionDescriptor.hpp" #include "Descriptors/MoleculeDescriptor.hpp" #include "Descriptors/MoleculeDescriptor_impl.hpp" #include "Descriptors/MoleculeIdDescriptor.hpp" #include "Descriptors/MoleculeSelectionDescriptor.hpp" #include "Descriptors/SelectiveConstIterator_impl.hpp" #include "Descriptors/SelectiveIterator_impl.hpp" #include "Element/periodentafel.hpp" #include "Fragmentation/Homology/HomologyContainer.hpp" #include "Graph/BondGraph.hpp" #include "Graph/DepthFirstSearchAnalysis.hpp" #include "Helpers/defs.hpp" #include "LinearAlgebra/RealSpaceMatrix.hpp" #include "LinkedCell/LinkedCell_Controller.hpp" #include "LinkedCell/PointCloudAdaptor.hpp" #include "molecule.hpp" #include "Thermostats/ThermoStatContainer.hpp" #include "WorldTime.hpp" #include "IdPool_impl.hpp" #include "CodePatterns/IteratorAdaptors.hpp" #include "CodePatterns/Singleton_impl.hpp" #include "CodePatterns/Observer/Channels.hpp" #include "CodePatterns/Observer/ObservedContainer_impl.hpp" using namespace MoleCuilder; /******************************* Notifications ************************/ atom* World::_lastchangedatom = NULL; atomId_t World::_lastchangedatomid = -1; molecule* World::_lastchangedmol = NULL; moleculeId_t World::_lastchangedmolid = -1; /******************************* getter and setter ************************/ periodentafel *&World::getPeriode() { return periode; } BondGraph *&World::getBondGraph() { return BG; } HomologyContainer &World::getHomologies() { return *homologies; } void World::resetHomologies(HomologyContainer *&_homologies) { HomologyContainer *oldhomologies = homologies; // install new instance, resetting given pointer homologies = _homologies; _homologies = NULL; // delete old instance which also informs all observers delete oldhomologies; } void World::setBondGraph(BondGraph *_BG){ delete (BG); BG = _BG; } config *&World::getConfig(){ return configuration; } // Atoms atom* World::getAtom(AtomDescriptor descriptor){ return descriptor.find(); } const atom* World::getAtom(AtomDescriptor descriptor) const{ return const_cast(descriptor).find(); } World::AtomComposite World::getAllAtoms(AtomDescriptor descriptor){ return descriptor.findAll(); } World::ConstAtomComposite World::getAllAtoms(AtomDescriptor descriptor) const { return const_cast(descriptor).findAll(); } World::AtomComposite World::getAllAtoms(){ return getAllAtoms(AllAtoms()); } World::ConstAtomComposite World::getAllAtoms() const { return getAllAtoms(AllAtoms()); } int World::numAtoms() const { return atoms.size(); } // Molecules molecule *World::getMolecule(MoleculeDescriptor descriptor){ return descriptor.find(); } const molecule *World::getMolecule(MoleculeDescriptor descriptor) const { return const_cast(descriptor).find(); } std::vector World::getAllMolecules(MoleculeDescriptor descriptor){ return descriptor.findAll(); } std::vector World::getAllMolecules(MoleculeDescriptor descriptor) const { return const_cast(descriptor).findAll(); } std::vector World::getAllMolecules(){ return getAllMolecules(AllMolecules()); } std::vector World::getAllMolecules() const { return getAllMolecules(AllMolecules()); } int World::numMolecules() const { return molecules.size(); } // system Box& World::getDomain() { return *cell_size; } void World::setDomain(const RealSpaceMatrix &mat){ OBSERVE; *cell_size = mat; } void World::setDomain(double * matrix) { OBSERVE; RealSpaceMatrix M = ReturnFullMatrixforSymmetric(matrix); cell_size->setM(M); } LinkedCell::LinkedCell_View World::getLinkedCell(double distance) { ASSERT( distance >= 0, "World::getLinkedCell() - distance is not positive."); if (distance < 1.) { ELOG(2, "Linked cell grid with length less than 1. is very memory-intense!"); distance = 1.; } // we have to grope past the ObservedContainer mechanism and transmorph the map // into a traversable list for the adaptor PointCloudAdaptor< AtomSet::set_t, MapValueIterator > atomset( &(atoms.getContent()), std::string("WorldsAtoms")); return LCcontroller->getView(distance, atomset); } const unsigned World::getTime() const { return WorldTime::getTime(); } bool areBondsPresent(const unsigned int _step) { bool status = false; for (World::AtomConstIterator iter = const_cast(World::getInstance()).getAtomIter(); (!status) && (iter != const_cast(World::getInstance()).atomEnd()); ++iter) { const atom * const Walker = *iter; status |= !Walker->getListOfBondsAtStep(_step).empty(); } return status; } void copyBondgraph(const unsigned int _srcstep, const unsigned int _deststep) { // gather all bonds from _srcstep std::set SetOfBonds; for (World::AtomConstIterator iter = const_cast(World::getInstance()).getAtomIter(); iter != const_cast(World::getInstance()).atomEnd(); ++iter) { const atom * const Walker = *iter; const BondList bonds = Walker->getListOfBondsAtStep(_srcstep); BOOST_FOREACH( bond::ptr bondptr, bonds) { SetOfBonds.insert(bondptr.get()); } } LOG(4, "DEBUG: We gathered " << SetOfBonds.size() << " bonds in total."); // copy bond to new time step for (std::set::const_iterator bonditer = SetOfBonds.begin(); bonditer != SetOfBonds.end(); ++bonditer) { const atom * const Walker = (*bonditer)->leftatom; const atom * const OtherWalker = (*bonditer)->rightatom; bond::ptr const _bond = const_cast(Walker)->addBond(_deststep, const_cast(OtherWalker)); _bond->setDegree((*bonditer)->getDegree()); } } void World::setTime(const unsigned int _step) { if (_step != WorldTime::getTime()) { const unsigned int oldstep = WorldTime::getTime(); // 1. copy bond graph (such not each addBond causes GUI update) if (!areBondsPresent(_step)) { // AtomComposite Set = getAllAtoms(); // BG->cleanAdjacencyList(Set); copyBondgraph(oldstep, _step); } // 2. set new time WorldTime::getInstance().setTime(_step); // 4. scan for connected subgraphs => molecules DepthFirstSearchAnalysis DFS; DFS(); DFS.UpdateMoleculeStructure(); } } std::string World::getDefaultName() { return defaultName; } void World::setDefaultName(std::string name) { OBSERVE; defaultName = name; }; class ThermoStatContainer * World::getThermostats() { return Thermostats; } int World::getExitFlag() { return ExitFlag; } void World::setExitFlag(int flag) { if (ExitFlag < flag) ExitFlag = flag; } /******************** Methods to change World state *********************/ molecule* World::createMolecule(){ OBSERVE; molecule *mol = NULL; mol = NewMolecule(); moleculeId_t id = moleculeIdPool.getNextId(); ASSERT(!molecules.count(id),"proposed id did not specify an unused ID"); mol->setId(id); // store the molecule by ID molecules[mol->getId()] = mol; _lastchangedmol = mol; _lastchangedmolid = mol->getId(); NOTIFY(MoleculeInserted); return mol; } molecule* World::recreateMolecule(const moleculeId_t &_id) { molecule *mol = NULL; if (!molecules.count(_id)) { OBSERVE; mol = NewMolecule(); mol->setId(_id); // store the molecule by ID molecules[mol->getId()] = mol; _lastchangedmol = mol; _lastchangedmolid = mol->getId(); NOTIFY(MoleculeInserted); } return mol; } void World::destroyMolecule(molecule* mol){ ASSERT(mol,"Molecule that was meant to be destroyed did not exist"); destroyMolecule(mol->getId()); } void World::destroyMolecule(moleculeId_t id){ molecule *mol = molecules[id]; ASSERT(mol,"Molecule id that was meant to be destroyed did not exist"); // give notice about immediate removal { OBSERVE; _lastchangedmol = mol; _lastchangedmolid = mol->getId(); NOTIFY(MoleculeRemoved); } if (isMoleculeSelected(id)) { selectedMolecules.erase(id); NOTIFY(SelectionChanged); } DeleteMolecule(mol); molecules.erase(id); moleculeIdPool.releaseId(id); } atom *World::createAtom(){ OBSERVE; atomId_t id = atomIdPool.getNextId(); ASSERT(!atoms.count(id),"proposed id did not specify an unused ID"); atom *res = NewAtom(id); res->setWorld(this); // store the atom by ID atoms[res->getId()] = res; _lastchangedatom = res; _lastchangedatomid = res->getId(); NOTIFY(AtomInserted); return res; } atom *World::recreateAtom(const atomId_t _id){ if (!atoms.count(_id)) { OBSERVE; atom *res = NewAtom(_id); res->setWorld(this); // store the atom by ID atoms[res->getId()] = res; _lastchangedatom = res; _lastchangedatomid = res->getId(); NOTIFY(AtomInserted); return res; } else return NULL; } int World::registerAtom(atom *atom){ OBSERVE; atomId_t id = atomIdPool.getNextId(); atom->setId(id); atom->setWorld(this); atoms[atom->getId()] = atom; _lastchangedatom = atom; _lastchangedatomid = atom->getId(); NOTIFY(AtomInserted); return atom->getId(); } void World::destroyAtom(atom* atom){ int id = atom->getId(); destroyAtom(id); } void World::destroyAtom(atomId_t id) { atom *atom = atoms[id]; ASSERT(atom,"Atom ID that was meant to be destroyed did not exist"); // give notice about immediate removal { OBSERVE; _lastchangedatom = atom; _lastchangedatomid = atom->getId(); NOTIFY(AtomRemoved); } // check if it's the last atom molecule *_mol = const_cast(atom->getMolecule()); if ((_mol == NULL) || (_mol->getAtomCount() > 1)) _mol = NULL; if (isAtomSelected(id)) { selectedAtoms.erase(id); NOTIFY(SelectionChanged); } DeleteAtom(atom); atoms.erase(id); atomIdPool.releaseId(id); // remove molecule if empty if (_mol != NULL) destroyMolecule(_mol); } bool World::changeAtomId(atomId_t oldId, atomId_t newId, atom* target){ OBSERVE; // in case this call did not originate from inside the atom, we redirect it, // to also let it know that it has changed if(!target){ target = atoms[oldId]; ASSERT(target,"Atom with that ID not found"); return target->changeId(newId); } else{ if(atomIdPool.reserveId(newId)){ atoms.erase(oldId); atoms.insert(pair(newId,target)); return true; } else{ return false; } } } bool World::changeMoleculeId(moleculeId_t oldId, moleculeId_t newId, molecule* target){ OBSERVE; // in case this call did not originate from inside the atom, we redirect it, // to also let it know that it has changed if(!target){ target = molecules[oldId]; ASSERT(target,"Molecule with that ID not found"); return target->changeId(newId); } else{ if(moleculeIdPool.reserveId(newId)){ molecules.erase(oldId); molecules.insert(pair(newId,target)); return true; } else{ return false; } } } ManipulateAtomsProcess* World::manipulateAtoms(boost::function op,std::string name,AtomDescriptor descr){ ActionTrait manipulateTrait(name); return new ManipulateAtomsProcess(op, descr,manipulateTrait); } ManipulateAtomsProcess* World::manipulateAtoms(boost::function op,std::string name){ return manipulateAtoms(op,name,AllAtoms()); } /********************* Internal Change methods for double Callback and Observer mechanism ********/ void World::doManipulate(ManipulateAtomsProcess *proc){ proc->signOn(this); { OBSERVE; proc->doManipulate(this); } proc->signOff(this); } /******************************* Iterators ********************************/ // external parts with observers CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet,AtomDescriptor) CONSTRUCT_SELECTIVE_CONST_ITERATOR(atom*,World::AtomSet,AtomDescriptor) World::AtomIterator World::getAtomIter(AtomDescriptor descr){ return AtomIterator(descr,atoms); } World::AtomConstIterator World::getAtomIter(AtomDescriptor descr) const{ return AtomConstIterator(descr,atoms); } World::AtomIterator World::getAtomIter(){ return AtomIterator(AllAtoms(),atoms); } World::AtomConstIterator World::getAtomIter() const{ return AtomConstIterator(AllAtoms(),atoms); } World::AtomIterator World::atomEnd(){ return AtomIterator(AllAtoms(),atoms,atoms.end()); } World::AtomConstIterator World::atomEnd() const{ return AtomConstIterator(AllAtoms(),atoms,atoms.end()); } CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor) CONSTRUCT_SELECTIVE_CONST_ITERATOR(molecule*,World::MoleculeSet,MoleculeDescriptor) World::MoleculeIterator World::getMoleculeIter(MoleculeDescriptor descr){ return MoleculeIterator(descr,molecules); } World::MoleculeConstIterator World::getMoleculeIter(MoleculeDescriptor descr) const{ return MoleculeConstIterator(descr,molecules); } World::MoleculeIterator World::getMoleculeIter(){ return MoleculeIterator(AllMolecules(),molecules); } World::MoleculeConstIterator World::getMoleculeIter() const{ return MoleculeConstIterator(AllMolecules(),molecules); } World::MoleculeIterator World::moleculeEnd(){ return MoleculeIterator(AllMolecules(),molecules,molecules.end()); } World::MoleculeConstIterator World::moleculeEnd() const{ return MoleculeConstIterator(AllMolecules(),molecules,molecules.end()); } // Internal parts, without observers // Build the AtomIterator from template CONSTRUCT_SELECTIVE_ITERATOR(atom*,World::AtomSet::set_t,AtomDescriptor); World::internal_AtomIterator World::getAtomIter_internal(AtomDescriptor descr){ return internal_AtomIterator(descr,atoms.getContent()); } World::internal_AtomIterator World::atomEnd_internal(){ return internal_AtomIterator(AllAtoms(),atoms.getContent(),atoms.end_internal()); } // build the MoleculeIterator from template CONSTRUCT_SELECTIVE_ITERATOR(molecule*,World::MoleculeSet::set_t,MoleculeDescriptor); World::internal_MoleculeIterator World::getMoleculeIter_internal(MoleculeDescriptor descr){ return internal_MoleculeIterator(descr,molecules.getContent()); } World::internal_MoleculeIterator World::moleculeEnd_internal(){ return internal_MoleculeIterator(AllMolecules(),molecules.getContent(),molecules.end_internal()); } /************************** Selection of Atoms and molecules ******************/ // translate type's selection member functions to overloaded with specific type template void World::selectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end) { std::for_each(_begin,_end, boost::bind(&World::selectInstance, boost::bind(_take::get, _1))); } template void World::unselectVectorOfInstances(const typename T::iterator _begin, const typename T::iterator _end) { std::for_each(_begin,_end, boost::bind(&World::unselectInstance, boost::bind(_take::get, _1))); } // Atoms void World::clearAtomSelection(){ OBSERVE; NOTIFY(SelectionChanged); unselectVectorOfInstances(selectedAtoms.begin(), selectedAtoms.end()); selectedAtoms.clear(); } void World::invertAtomSelection(){ // get all atoms not selected AtomComposite invertedSelection(getAllAtoms()); bool (World::*predicate)(const atom*) const = &World::isSelected; // needed for type resolution of overloaded function AtomComposite::iterator iter = std::remove_if(invertedSelection.begin(), invertedSelection.end(), std::bind1st(std::mem_fun(predicate), this)); invertedSelection.erase(iter, invertedSelection.end()); // apply new selection unselectVectorOfInstances(selectedAtoms.begin(), selectedAtoms.end()); selectedAtoms.clear(); void (World::*selector)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function std::for_each(invertedSelection.begin(),invertedSelection.end(), std::bind1st(std::mem_fun(selector),this)); // func is select... see above } void World::popAtomSelection(){ if (!selectedAtoms_Stack.empty()) { OBSERVE; NOTIFY(SelectionChanged); const atomIdsVector_t atomids = selectedAtoms_Stack.top(); boost::function IdSelector = boost::bind(static_cast(&World::selectAtom), this, _1); unselectVectorOfInstances(selectedAtoms.begin(), selectedAtoms.end()); selectedAtoms.clear(); std::for_each(atomids.begin(),atomids.end(), IdSelector); selectedAtoms_Stack.pop(); } } void World::pushAtomSelection(){ OBSERVE; NOTIFY(SelectionChanged); atomIdsVector_t atomids(countSelectedAtoms(), (atomId_t)-1); std::copy( MapKeyIterator(beginAtomSelection()), MapKeyIterator(endAtomSelection()), atomids.begin()); selectedAtoms_Stack.push( atomids ); unselectVectorOfInstances(selectedAtoms.begin(), selectedAtoms.end()); selectedAtoms.clear(); } void World::selectAtom(const atom *_atom){ OBSERVE; NOTIFY(SelectionChanged); // atom * is unchanged in this function, but we do store entity as changeable ASSERT(_atom,"Invalid pointer in selection of atom"); selectAtom(_atom->getId()); } void World::selectAtom(const atomId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(atoms.count(id),"Atom Id selected that was not in the world"); selectedAtoms[id]=atoms[id]; atoms[id]->select(); } void World::selectAllAtoms(AtomDescriptor descr){ OBSERVE; NOTIFY(SelectionChanged); internal_AtomIterator begin = getAtomIter_internal(descr); internal_AtomIterator end = atomEnd_internal(); void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above } void World::selectAtomsOfMolecule(const molecule *_mol){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule"); // need to make it const to get the fast iterators const molecule *mol = _mol; void (World::*func)(const atom*) = &World::selectAtom; // needed for type resolution of overloaded function for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is select... see above } void World::selectAtomsOfMolecule(const moleculeId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule"); selectAtomsOfMolecule(molecules[id]); } void World::unselectAtom(const atom *_atom){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_atom,"Invalid pointer in unselection of atom"); unselectAtom(_atom->getId()); } void World::unselectAtom(const atomId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(atoms.count(id),"Atom Id unselected that was not in the world"); atoms[id]->unselect(); selectedAtoms.erase(id); } void World::unselectAllAtoms(AtomDescriptor descr){ OBSERVE; NOTIFY(SelectionChanged); internal_AtomIterator begin = getAtomIter_internal(descr); internal_AtomIterator end = atomEnd_internal(); void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above } void World::unselectAtomsOfMolecule(const molecule *_mol){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_mol,"Invalid pointer to molecule in selection of Atoms of Molecule"); // need to make it const to get the fast iterators const molecule *mol = _mol; void (World::*func)(const atom*) = &World::unselectAtom; // needed for type resolution of overloaded function for_each(mol->begin(),mol->end(),bind1st(mem_fun(func),this)); // func is unselect... see above } void World::unselectAtomsOfMolecule(const moleculeId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(molecules.count(id),"No molecule with the given id upon Selection of atoms from molecule"); unselectAtomsOfMolecule(molecules[id]); } size_t World::countSelectedAtoms() const { size_t count = 0; for (AtomSet::const_iterator iter = selectedAtoms.begin(); iter != selectedAtoms.end(); ++iter) count++; return count; } bool World::isSelected(const atom *_atom) const { const bool status = isAtomSelected(_atom->getId()); ASSERT( status == _atom->selected, "World::isSelected() - mismatch between selection state in atom "+ toString(_atom->getId())+" and World."); return status; } bool World::isAtomSelected(const atomId_t no) const { return selectedAtoms.find(no) != selectedAtoms.end(); } std::vector World::getSelectedAtoms() { std::vector returnAtoms; std::transform( selectedAtoms.begin(), selectedAtoms.end(), back_inserter(returnAtoms), _take::get); return returnAtoms; } std::vector World::getSelectedAtoms() const { std::vector returnAtoms; std::transform( selectedAtoms.begin(), selectedAtoms.end(), back_inserter(returnAtoms), _take::get); return returnAtoms; } std::vector World::getSelectedAtomIds() const { std::vector returnAtomIds; std::transform( selectedAtoms.begin(), selectedAtoms.end(), back_inserter(returnAtomIds), _take::getKey); return returnAtomIds; } // Molecules void World::clearMoleculeSelection(){ OBSERVE; NOTIFY(SelectionChanged); unselectVectorOfInstances(selectedMolecules.begin(), selectedMolecules.end()); selectedMolecules.clear(); } void World::invertMoleculeSelection(){ // get all molecules not selected typedef std::vector MoleculeVector_t; MoleculeVector_t invertedSelection(getAllMolecules()); bool (World::*predicate)(const molecule*) const = &World::isSelected; // needed for type resolution of overloaded function MoleculeVector_t::iterator iter = std::remove_if(invertedSelection.begin(), invertedSelection.end(), std::bind1st(std::mem_fun(predicate), this)); invertedSelection.erase(iter, invertedSelection.end()); // apply new selection unselectVectorOfInstances(selectedMolecules.begin(), selectedMolecules.end()); selectedMolecules.clear(); void (World::*selector)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function std::for_each(invertedSelection.begin(),invertedSelection.end(), std::bind1st(std::mem_fun(selector),this)); // func is select... see above } void World::popMoleculeSelection(){ if (!selectedMolecules_Stack.empty()) { OBSERVE; NOTIFY(SelectionChanged); const moleculeIdsVector_t moleculeids = selectedMolecules_Stack.top(); boost::function IdSelector = boost::bind(static_cast(&World::selectMolecule), this, _1); unselectVectorOfInstances(selectedMolecules.begin(), selectedMolecules.end()); selectedMolecules.clear(); std::for_each(moleculeids.begin(),moleculeids.end(), IdSelector); selectedMolecules_Stack.pop(); } } void World::pushMoleculeSelection(){ OBSERVE; NOTIFY(SelectionChanged); moleculeIdsVector_t moleculeids(countSelectedMolecules(), (moleculeId_t)-1); boost::function IdRetriever = boost::bind(&molecule::getId, _1); std::copy( MapKeyIterator(beginMoleculeSelection()), MapKeyIterator(endMoleculeSelection()), moleculeids.begin()); selectedMolecules_Stack.push( moleculeids ); unselectVectorOfInstances(selectedMolecules.begin(), selectedMolecules.end()); selectedMolecules.clear(); } void World::selectMolecule(const molecule *_mol){ OBSERVE; NOTIFY(SelectionChanged); // molecule * is unchanged in this function, but we do store entity as changeable ASSERT(_mol,"Invalid pointer to molecule in selection"); selectMolecule(_mol->getId()); } void World::selectMolecule(const moleculeId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(molecules.count(id),"Molecule Id selected that was not in the world"); molecules[id]->select(); selectedMolecules[id]=molecules[id]; } void World::selectAllMolecules(MoleculeDescriptor descr){ OBSERVE; NOTIFY(SelectionChanged); internal_MoleculeIterator begin = getMoleculeIter_internal(descr); internal_MoleculeIterator end = moleculeEnd_internal(); void (World::*func)(const molecule*) = &World::selectMolecule; // needed for type resolution of overloaded function for_each(begin,end,bind1st(mem_fun(func),this)); // func is select... see above } void World::selectMoleculeOfAtom(const atom *_atom){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom"); const molecule *mol=_atom->getMolecule(); // the atom might not be part of a molecule if(mol){ selectMolecule(mol); } } void World::selectMoleculeOfAtom(const atomId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\ selectMoleculeOfAtom(atoms[id]); } void World::unselectMolecule(const molecule *_mol){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_mol,"invalid pointer in unselection of molecule"); unselectMolecule(_mol->getId()); } void World::unselectMolecule(const moleculeId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(molecules.count(id),"No such molecule with ID in unselection"); molecules[id]->unselect(); selectedMolecules.erase(id); } void World::unselectAllMolecules(MoleculeDescriptor descr){ OBSERVE; NOTIFY(SelectionChanged); internal_MoleculeIterator begin = getMoleculeIter_internal(descr); internal_MoleculeIterator end = moleculeEnd_internal(); void (World::*func)(const molecule*) = &World::unselectMolecule; // needed for type resolution of overloaded function for_each(begin,end,bind1st(mem_fun(func),this)); // func is unselect... see above } void World::unselectMoleculeOfAtom(const atom *_atom){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(_atom,"Invalid atom pointer in selection of MoleculeOfAtom"); const molecule *mol=_atom->getMolecule(); // the atom might not be part of a molecule if(mol){ unselectMolecule(mol); } } void World::unselectMoleculeOfAtom(const atomId_t id){ OBSERVE; NOTIFY(SelectionChanged); ASSERT(atoms.count(id),"No such atom with given ID in selection of Molecules of Atom");\ unselectMoleculeOfAtom(atoms[id]); } size_t World::countSelectedMolecules() const { size_t count = 0; for (MoleculeSet::const_iterator iter = selectedMolecules.begin(); iter != selectedMolecules.end(); ++iter) count++; return count; } bool World::isSelected(const molecule *_mol) const { const bool status = isMoleculeSelected(_mol->getId()); ASSERT( status == _mol->selected, "World::isSelected() - mismatch in selection status between mol "+ toString(_mol->getId())+" and World."); return status; } bool World::isMoleculeSelected(const moleculeId_t no) const { return selectedMolecules.find(no) != selectedMolecules.end(); } std::vector World::getSelectedMolecules() { std::vector returnMolecules; std::transform( selectedMolecules.begin(), selectedMolecules.end(), back_inserter(returnMolecules), _take::get); return returnMolecules; } std::vector World::getSelectedMolecules() const { std::vector returnMolecules; std::transform( selectedMolecules.begin(), selectedMolecules.end(), back_inserter(returnMolecules), _take::get); return returnMolecules; } std::vector World::getSelectedMoleculeIds() const { std::vector returnMoleculeIds; std::transform( selectedMolecules.begin(), selectedMolecules.end(), back_inserter(returnMoleculeIds), _take::getKey); return returnMoleculeIds; } /******************* Iterators over Selection *****************************/ World::AtomSelectionIterator World::beginAtomSelection(){ return selectedAtoms.begin(); } World::AtomSelectionIterator World::endAtomSelection(){ return selectedAtoms.end(); } World::AtomSelectionConstIterator World::beginAtomSelection() const{ return selectedAtoms.begin(); } World::AtomSelectionConstIterator World::endAtomSelection() const{ return selectedAtoms.end(); } World::MoleculeSelectionIterator World::beginMoleculeSelection(){ return selectedMolecules.begin(); } World::MoleculeSelectionIterator World::endMoleculeSelection(){ return selectedMolecules.end(); } World::MoleculeSelectionConstIterator World::beginMoleculeSelection() const{ return selectedMolecules.begin(); } World::MoleculeSelectionConstIterator World::endMoleculeSelection() const{ return selectedMolecules.end(); } /******************************* Singleton Stuff **************************/ World::World() : Observable("World"), BG(new BondGraph(true)), // assume Angstroem for the moment periode(new periodentafel(true)), configuration(new config), homologies(new HomologyContainer()), Thermostats(new ThermoStatContainer), ExitFlag(0), atoms(this), selectedAtoms(this), atomIdPool(0, 20, 100), molecules(this), selectedMolecules(this), moleculeIdPool(0, 20,100) { cell_size = new Box; RealSpaceMatrix domain; domain.at(0,0) = 20; domain.at(1,1) = 20; domain.at(2,2) = 20; cell_size->setM(domain); LCcontroller = new LinkedCell::LinkedCell_Controller(*cell_size); defaultName = "none"; Channels *OurChannel = new Channels; Observable::insertNotificationChannel( std::make_pair( static_cast(this), OurChannel) ); for (size_t type = 0; type < (size_t)NotificationType_MAX; ++type) OurChannel->addChannel(type); } World::~World() { delete LCcontroller; delete cell_size; MoleculeSet::iterator molIter; for(molIter=molecules.begin();molIter!=molecules.end();++molIter){ DeleteMolecule((*molIter).second); } molecules.clear(); AtomSet::iterator atIter; for(atIter=atoms.begin();atIter!=atoms.end();++atIter){ DeleteAtom((*atIter).second); } atoms.clear(); delete BG; delete periode; delete configuration; delete Thermostats; delete homologies; } // Explicit instantiation of the singleton mechanism at this point // moleculeId_t und atomId_t sind gleicher Basistyp, deswegen nur einen von beiden konstruieren CONSTRUCT_IDPOOL(atomId_t, uniqueId) CONSTRUCT_IDPOOL(moleculeId_t, continuousId) CONSTRUCT_SINGLETON(World) CONSTRUCT_OBSERVEDCONTAINER(World::AtomSTLSet, UnobservedIterator ) CONSTRUCT_OBSERVEDCONTAINER(World::MoleculeSTLSet, UnobservedIterator )