/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2016 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 . */ /* * BondSetDegreeAction.cpp * * Created on: Oct 01, 2016 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif //#include "CodePatterns/MemDebug.hpp" #include "Atom/atom.hpp" #include "Bond/bond.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/Verbose.hpp" #include "Descriptors/AtomIdDescriptor.hpp" #include "World.hpp" #include "WorldTime.hpp" #include #include #include "Actions/BondAction/BondSetDegreeAction.hpp" using namespace MoleCuilder; // and construct the stuff #include "BondSetDegreeAction.def" #include "Action_impl_pre.hpp" /** =========== define the function ====================== */ ActionState::ptr BondSetDegreeAction::performCall() { // check preconditions World& world = World::getInstance(); if (world.countSelectedAtoms() <= 1) { ELOG(1, "There must be at least two atoms selected for BondSetDegreeAction."); return Action::failure; } for (World::AtomSelectionConstIterator firstiter = world.beginAtomSelection(); firstiter != world.endAtomSelection(); ++firstiter) { bool status = false; for (World::AtomSelectionConstIterator seconditer = world.beginAtomSelection(); seconditer != world.endAtomSelection(); ++seconditer) { if (firstiter == seconditer) continue; if ((firstiter->second)->IsBondedTo(WorldTime::getTime(), seconditer->second)) { status = true; } } if (!status) { ELOG(1, "Selected atom #" << firstiter->second->getId() << " has no bonds."); return Action::failure; } } // store current degrees in vector BondDegrees_t BondDegrees; for (World::AtomSelectionConstIterator firstiter = world.beginAtomSelection(); firstiter != world.endAtomSelection(); ++firstiter) { for (World::AtomSelectionConstIterator seconditer = firstiter; seconditer != world.endAtomSelection(); ++seconditer) { if (firstiter == seconditer) continue; if ((firstiter->second)->IsBondedTo(WorldTime::getTime(), seconditer->second)) { bond::ptr bond = (firstiter->second)->getBond(seconditer->second); BondInfo bondinfo(bond); BondDegrees.push_back( bondinfo ); } } } if (BondDegrees.empty()) { ELOG(1, "All bonds are already present."); return Action::failure; } // create undo state BondSetDegreeState *UndoState = new BondSetDegreeState(BondDegrees, params); // execute action for (BondDegrees_t::const_iterator iter = BondDegrees.begin(); iter != BondDegrees.end(); ++iter) { atom *firstatom = world.getAtom(AtomById((*iter).leftid)); atom *secondatom = world.getAtom(AtomById((*iter).rightid)); ASSERT((firstatom != NULL) && (secondatom != NULL), "BondSetDegreeAction::performCall() - at least one of the ids " +toString((*iter).leftid)+" or "+toString((*iter).rightid)+" is not present."); const bond::ptr bond = firstatom->getBond(secondatom); bond->setDegree(params.degree.get()); } return ActionState::ptr(UndoState); } ActionState::ptr BondSetDegreeAction::performUndo(ActionState::ptr _state) { BondSetDegreeState *state = assert_cast(_state.get()); // check whether bond already existed World& world = World::getInstance(); for (BondDegrees_t::const_iterator iter = state->bonddegrees.begin(); iter != state->bonddegrees.end(); ++iter) { atom *firstatom = world.getAtom(AtomById((*iter).leftid)); atom *secondatom = world.getAtom(AtomById((*iter).rightid)); ASSERT((firstatom != NULL) && (secondatom != NULL), "BondSetDegreeAction::performUndo() - at least one of the ids " +toString((*iter).leftid)+" or "+toString((*iter).rightid)+" is not present."); if (firstatom->IsBondedTo(WorldTime::getTime(), secondatom)) { const bond::ptr bond = firstatom->getBond(secondatom); bond->setDegree((*iter).degree); } else { ELOG(2, "There is no bond in between "+toString((*iter).leftid) +" and "+toString((*iter).rightid)+"."); } } return ActionState::ptr(_state); } ActionState::ptr BondSetDegreeAction::performRedo(ActionState::ptr _state){ BondSetDegreeState *state = assert_cast(_state.get()); // check whether bond already existed World& world = World::getInstance(); for (BondDegrees_t::const_iterator iter = state->bonddegrees.begin(); iter != state->bonddegrees.end(); ++iter) { atom * const firstatom = world.getAtom(AtomById((*iter).leftid)); atom * const secondatom = world.getAtom(AtomById((*iter).rightid)); ASSERT((firstatom != NULL) && (secondatom != NULL), "BondSetDegreeAction::performRedo() - at least one of the ids " +toString((*iter).leftid)+" or "+toString((*iter).rightid)+" is not present."); if (firstatom->IsBondedTo(WorldTime::getTime(), secondatom)) { const bond::ptr bond = firstatom->getBond(secondatom); bond->setDegree(state->params.degree.get()); } else { ELOG(2, "There is no bond in between "+toString((*iter).leftid) +" and "+toString((*iter).rightid)+"."); } } return ActionState::ptr(_state); } bool BondSetDegreeAction::canUndo() { return true; } bool BondSetDegreeAction::shouldUndo() { return true; } /** =========== end of function ====================== */