source: src/Actions/BondAction/BondAddAction.cpp@ c30959

Candidate_v1.7.0 stable
Last change on this file since c30959 was c30959, checked in by Frederik Heber <frederik.heber@…>, 5 years ago

BondAddAction also adds to molecule.

  • NOTE: This basically does nothing as new atoms (AddAtom action) always get a dummy molecule. However, removing them from the dummy molecule and readding one is quite complicated.
  • if we add bonds between new atoms (without a molecule set) to and atoms belonging all to the same molecule, then we automatically add the new atoms to this molecule as well. This saves the need for any GraphUpdateMolecules() call afterwards.
  • also implemented undo and redo for this.
  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * BondAddAction.cpp
25 *
26 * Created on: Nov 12, 2012
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include "Atom/atom.hpp"
38#include "Bond/bond.hpp"
39#include "CodePatterns/Assert.hpp"
40#include "CodePatterns/Log.hpp"
41#include "CodePatterns/Verbose.hpp"
42#include "Descriptors/AtomIdDescriptor.hpp"
43#include "molecule.hpp"
44#include "World.hpp"
45#include "WorldTime.hpp"
46
47#include <iostream>
48#include <string>
49
50#include "Actions/BondAction/BondAddAction.hpp"
51
52using namespace MoleCuilder;
53
54// and construct the stuff
55#include "BondAddAction.def"
56#include "Action_impl_pre.hpp"
57/** =========== define the function ====================== */
58ActionState::ptr BondAddAction::performCall() {
59 // check preconditions
60 World& world = World::getInstance();
61 if (world.countSelectedAtoms() <= 1) {
62 STATUS("There must be at least two atoms selected for BondAction Add.");
63 return Action::failure;
64 }
65
66 // check if we are adding new atoms to a molecule
67 molecules_t molecules;
68 const molecule *add_to_mol_const = NULL;
69 molecules.reserve(world.countSelectedAtoms());
70 for (World::AtomSelectionConstIterator firstiter = world.beginAtomSelection();
71 firstiter != world.endAtomSelection(); ++firstiter) {
72 const molecule * const current_mol = firstiter->second->getMolecule();
73 molecules.push_back(current_mol);
74 if (current_mol != NULL) {
75 if (add_to_mol_const == NULL)
76 add_to_mol_const = current_mol;
77 else if (add_to_mol_const != current_mol) {
78 // we encountered a second molecule, don't set the molecules
79 molecules.clear();
80 add_to_mol_const = NULL;
81 break;
82 }
83 }
84 }
85
86 bondPairIds_t bondPairIds;
87 for (World::AtomSelectionConstIterator firstiter = world.beginAtomSelection();
88 firstiter != world.endAtomSelection(); ++firstiter) {
89 for (World::AtomSelectionConstIterator seconditer = firstiter;
90 seconditer != world.endAtomSelection(); ++seconditer) {
91 if (firstiter == seconditer)
92 continue;
93 if (!(firstiter->second)->IsBondedTo(WorldTime::getTime(), seconditer->second))
94 bondPairIds.push_back(
95 std::make_pair((firstiter->second)->getId(), (seconditer->second)->getId()));
96 }
97 }
98 if (bondPairIds.empty()) {
99 STATUS("All bonds are already present.");
100 return Action::failure;
101 }
102
103 // create undo
104 molecule *add_to_mol = NULL;
105 if (add_to_mol_const != NULL) {
106 add_to_mol = world.getMolecule(MoleculeById(add_to_mol_const->getId()));
107 ASSERT( add_to_mol != NULL,
108 "BondAddAction::performCall() - could not obtain molecule from World.");
109 }
110 BondAddState *UndoState = new BondAddState(bondPairIds, molecules, add_to_mol, params);
111
112 // execute action
113 for (bondPairIds_t::const_iterator iter = bondPairIds.begin();
114 iter != bondPairIds.end(); ++iter) {
115 atom * const firstatom = world.getAtom(AtomById(iter->first));
116 atom * const secondatom = world.getAtom(AtomById(iter->second));
117 ASSERT((firstatom != NULL) && (secondatom != NULL),
118 "BondAddAction::performCall() - at least one of the ids "
119 +toString(iter->first)+" or "+toString(iter->second)+" is not present.");
120 bond::ptr newbond = firstatom->addBond(WorldTime::getTime(), secondatom);
121 newbond->setDegree(params.degree.get());
122 ASSERT( firstatom->IsBondedTo(WorldTime::getTime(), secondatom),
123 "BondAddAction::performCall() - adding bond in between "
124 +toString(*firstatom)+" and "+toString(*secondatom)+" failed.");
125 }
126 if (add_to_mol != NULL)
127 for (World::AtomSelectionIterator firstiter = world.beginAtomSelection();
128 firstiter != world.endAtomSelection(); ++firstiter) {
129 if (firstiter->second->getMolecule() != add_to_mol)
130 add_to_mol->AddAtom(firstiter->second);
131 }
132
133 return ActionState::ptr(UndoState);
134}
135
136ActionState::ptr BondAddAction::performUndo(ActionState::ptr _state) {
137 BondAddState *state = assert_cast<BondAddState*>(_state.get());
138
139 // check whether bond already existed
140 World& world = World::getInstance();
141 for (bondPairIds_t::const_iterator iter = state->bondPairIds.begin();
142 iter != state->bondPairIds.end(); ++iter) {
143 atom *firstatom = world.getAtom(AtomById(iter->first));
144 atom *secondatom = world.getAtom(AtomById(iter->second));
145 ASSERT((firstatom != NULL) && (secondatom != NULL),
146 "BondAddAction::performCall() - at least one of the ids "
147 +toString(iter->first)+" or "+toString(iter->second)+" is not present.");
148 if (firstatom->IsBondedTo(WorldTime::getTime(), secondatom)) {
149 firstatom->removeBond(WorldTime::getTime(), secondatom);
150 } else {
151 ELOG(2, "There is no bond in between "+toString(iter->first)
152 +" and "+toString(iter->second)+".");
153 }
154 }
155 if (state->add_to_mol != NULL) {
156 molecules_t::const_iterator mol_iter = state->molecules.begin();
157 for (World::AtomSelectionIterator firstiter = world.beginAtomSelection();
158 firstiter != world.endAtomSelection(); ++firstiter) {
159 const molecule * const current_mol = *mol_iter++;
160 atom * const Walker = firstiter->second;
161 if (current_mol != Walker->getMolecule()) {
162 if (Walker->getMolecule() != NULL)
163 Walker->removeFromMolecule();
164 if (current_mol != NULL) {
165 molecule *add_to_mol = world.getMolecule(MoleculeById(current_mol->getId()));
166 add_to_mol->AddAtom(Walker);
167 }
168 }
169 }
170 ASSERT(mol_iter == state->molecules.end(),
171 "BondAddAction::performUndo() - number of molecule ptrs not coinciding with number of selected atoms.");
172 }
173
174 return ActionState::ptr(_state);
175}
176
177ActionState::ptr BondAddAction::performRedo(ActionState::ptr _state){
178 BondAddState *state = assert_cast<BondAddState*>(_state.get());
179
180 // check whether bond already existed
181 World& world = World::getInstance();
182 for (bondPairIds_t::const_iterator iter = state->bondPairIds.begin();
183 iter != state->bondPairIds.end(); ++iter) {
184 atom * const firstatom = world.getAtom(AtomById(iter->first));
185 atom * const secondatom = world.getAtom(AtomById(iter->second));
186 ASSERT((firstatom != NULL) && (secondatom != NULL),
187 "BondAddAction::performCall() - at least one of the ids "
188 +toString(iter->first)+" or "+toString(iter->second)+" is not present.");
189 if (!firstatom->IsBondedTo(WorldTime::getTime(), secondatom)) {
190 firstatom->addBond(WorldTime::getTime(), secondatom);
191 } else {
192 ELOG(2, "There is already a bond in between "+toString(iter->first)
193 +" and "+toString(iter->second)+".");
194 }
195 }
196 if (state->add_to_mol != NULL)
197 for (World::AtomSelectionIterator firstiter = world.beginAtomSelection();
198 firstiter != world.endAtomSelection(); ++firstiter) {
199 if (firstiter->second->getMolecule() != state->add_to_mol)
200 state->add_to_mol->AddAtom(firstiter->second);
201 }
202
203 return ActionState::ptr(_state);
204}
205
206bool BondAddAction::canUndo() {
207 return true;
208}
209
210bool BondAddAction::shouldUndo() {
211 return true;
212}
213/** =========== end of function ====================== */
Note: See TracBrowser for help on using the repository browser.